diff options
Diffstat (limited to 'datapath-windows')
-rw-r--r-- | datapath-windows/include/OvsDpInterfaceExt.h | 17 | ||||
-rw-r--r-- | datapath-windows/ovsext/Datapath.c | 104 | ||||
-rw-r--r-- | datapath-windows/ovsext/Datapath.h | 1 |
3 files changed, 119 insertions, 3 deletions
diff --git a/datapath-windows/include/OvsDpInterfaceExt.h b/datapath-windows/include/OvsDpInterfaceExt.h index 8850535ad..db91c3e1e 100644 --- a/datapath-windows/include/OvsDpInterfaceExt.h +++ b/datapath-windows/include/OvsDpInterfaceExt.h @@ -92,9 +92,12 @@ enum ovs_win_control_cmd { OVS_CTRL_CMD_MC_SUBSCRIBE_REQ, OVS_CTRL_CMD_PACKET_SUBSCRIBE_REQ, - /* This command is logically belong to the Vport family */ + /* This command logically belongs to the Vport family */ OVS_CTRL_CMD_EVENT_NOTIFY, - OVS_CTRL_CMD_READ_NOTIFY + OVS_CTRL_CMD_READ_NOTIFY, + + /* Used for Socket property */ + OVS_CTRL_CMD_SOCK_PROP }; /* NL Attributes for joining/unjoining an MC group */ @@ -163,4 +166,14 @@ enum ovs_win_netdev_attr { typedef struct ovs_dp_stats OVS_DP_STATS; typedef enum ovs_vport_type OVS_VPORT_TYPE; +/* NL Attributes for setting socket attributes */ +enum ovs_nl_sock_attr { + /* (UINT32) Netlink Protocol set in Userspace and read in Kernel */ + OVS_NL_ATTR_SOCK_PROTO, + /* (UINT32) Instance PID set in Kernel and read in Userspace */ + OVS_NL_ATTR_SOCK_PID, + __OVS_NL_ATTR_SOCK_MAX +}; +#define OVS_WIN_SOCK_ATTR_MAX (__OVS_NL_ATTR_SOCK_MAX - 1) + #endif /* __OVS_DP_INTERFACE_EXT_H_ */ diff --git a/datapath-windows/ovsext/Datapath.c b/datapath-windows/ovsext/Datapath.c index 16d58ef6e..4f47be575 100644 --- a/datapath-windows/ovsext/Datapath.c +++ b/datapath-windows/ovsext/Datapath.c @@ -87,7 +87,8 @@ static NetlinkCmdHandler OvsPendEventCmdHandler, OvsReadEventCmdHandler, OvsNewDpCmdHandler, OvsGetDpCmdHandler, - OvsSetDpCmdHandler; + OvsSetDpCmdHandler, + OvsSockPropCmdHandler; NetlinkCmdHandler OvsGetNetdevCmdHandler, OvsGetVportCmdHandler, @@ -147,6 +148,11 @@ NETLINK_CMD nlControlFamilyCmdOps[] = { .handler = OvsReadPacketCmdHandler, .supportedDevOp = OVS_READ_DEV_OP, .validateDpIndex = FALSE, + }, + { .cmd = OVS_CTRL_CMD_SOCK_PROP, + .handler = OvsSockPropCmdHandler, + .supportedDevOp = OVS_TRANSACTION_DEV_OP, + .validateDpIndex = FALSE, } }; @@ -1685,3 +1691,99 @@ OvsReadEventCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx, cleanup: return status; } + +/* + * -------------------------------------------------------------------------- + * Command Handler for 'OVS_CTRL_CMD_SOCK_PROP'. + * + * Handler to set and verify socket properties between userspace and kernel. + * + * Protocol is passed down by the userspace. It refers to the NETLINK family + * and could be of different types (NETLINK_GENERIC/NETLINK_NETFILTER etc.,) + * This function parses out the protocol and adds it to the open instance. + * + * PID is generated by the kernel and is set in userspace after querying the + * kernel for it. This function does not modify PID set in the kernel, + * instead it verifies if it was sent down correctly. + * + * XXX -This method can be modified to handle all Socket properties thereby + * eliminating the use of OVS_IOCTL_GET_PID + * + * -------------------------------------------------------------------------- + */ +static NTSTATUS +OvsSockPropCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx, + UINT32 *replyLen) +{ + static const NL_POLICY ovsSocketPolicy[] = { + [OVS_NL_ATTR_SOCK_PROTO] = { .type = NL_A_U32, .optional = TRUE }, + [OVS_NL_ATTR_SOCK_PID] = { .type = NL_A_U32, .optional = TRUE } + }; + PNL_ATTR attrs[ARRAY_SIZE(ovsSocketPolicy)]; + + if (usrParamsCtx->outputLength < sizeof(OVS_MESSAGE)) { + return STATUS_NDIS_INVALID_LENGTH; + } + + NL_BUFFER nlBuf; + POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer; + POVS_MESSAGE msgOut = (POVS_MESSAGE)usrParamsCtx->outputBuffer; + POVS_OPEN_INSTANCE instance = (POVS_OPEN_INSTANCE)usrParamsCtx->ovsInstance; + UINT32 protocol; + PNL_MSG_HDR nlMsg; + UINT32 pid; + + /* Parse the input */ + if (!NlAttrParse((PNL_MSG_HDR)msgIn, + NLMSG_HDRLEN + GENL_HDRLEN + OVS_HDRLEN, + NlMsgAttrsLen((PNL_MSG_HDR)msgIn), + ovsSocketPolicy, + ARRAY_SIZE(ovsSocketPolicy), + attrs, + ARRAY_SIZE(attrs))) { + return STATUS_INVALID_PARAMETER; + } + + /* Set the Protocol if it was passed down */ + if (attrs[OVS_NL_ATTR_SOCK_PROTO]) { + protocol = NlAttrGetU32(attrs[OVS_NL_ATTR_SOCK_PROTO]); + if (protocol) { + instance->protocol = protocol; + } + } + + /* Verify if the PID sent down matches the kernel */ + if (attrs[OVS_NL_ATTR_SOCK_PID]) { + pid = NlAttrGetU32(attrs[OVS_NL_ATTR_SOCK_PID]); + if (pid != instance->pid) { + OVS_LOG_ERROR("Received invalid pid:%d expected:%d", + pid, instance->pid); + return STATUS_INVALID_PARAMETER; + } + } + + /* Prepare the output */ + NlBufInit(&nlBuf, usrParamsCtx->outputBuffer, usrParamsCtx->outputLength); + if(!NlFillOvsMsg(&nlBuf, msgIn->nlMsg.nlmsgType, NLM_F_MULTI, + msgIn->nlMsg.nlmsgSeq, msgIn->nlMsg.nlmsgPid, + msgIn->genlMsg.cmd, msgIn->genlMsg.version, + gOvsSwitchContext->dpNo)){ + return STATUS_INVALID_BUFFER_SIZE; + } + + if (!NlMsgPutTailU32(&nlBuf, OVS_NL_ATTR_SOCK_PID, + instance->pid)) { + return STATUS_INVALID_BUFFER_SIZE; + } + + if (!NlMsgPutTailU32(&nlBuf, OVS_NL_ATTR_SOCK_PROTO, + instance->protocol)) { + return STATUS_INVALID_BUFFER_SIZE; + } + + nlMsg = (PNL_MSG_HDR)NlBufAt(&nlBuf, 0, 0); + nlMsg->nlmsgLen = NlBufSize(&nlBuf); + *replyLen = msgOut->nlMsg.nlmsgLen; + + return STATUS_SUCCESS; +} diff --git a/datapath-windows/ovsext/Datapath.h b/datapath-windows/ovsext/Datapath.h index 09e233fd3..2b41d82ac 100644 --- a/datapath-windows/ovsext/Datapath.h +++ b/datapath-windows/ovsext/Datapath.h @@ -51,6 +51,7 @@ typedef struct _OVS_OPEN_INSTANCE { PVOID eventQueue; POVS_USER_PACKET_QUEUE packetQueue; UINT32 pid; + UINT32 protocol; /* Refers to NETLINK Family (eg. NETLINK_GENERIC)*/ struct { POVS_MESSAGE ovsMsg; /* OVS message passed during dump start. */ |