From c8915346be1fab8640f517277d5dc278582cff21 Mon Sep 17 00:00:00 2001 From: Anand Kumar Date: Thu, 10 Jan 2019 16:45:24 -0800 Subject: datapath-windows: Add support for 'OVS_KEY_ATTR_ENCAP' key attribute. Add a new structure in l2 header to accomodate vlan header, based of commit "d7efce7beff25052bd9083419200e1a47f0d6066 datapath: 802.1AD Flow handling, actions, vlan parsing, netlink attributes" Also reset vlan header in flow key, after deleting vlan tag from nbl With this change a sample vlan flow would look like, eth(src=0a:ea:8a:24:03:86,dst=0a:cd:fa:4d:15:5c),in_port(3),eth_type(0x8100), vlan(vid=2239,pcp=0),encap(eth_type(0x0800),ipv4(src=13.12.11.149,dst=13.12.11.107, proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)) Signed-off-by: Anand Kumar Acked-by: Alin Gabriel Serdean Signed-off-by: Alin Gabriel Serdean --- datapath-windows/ovsext/Actions.c | 3 + datapath-windows/ovsext/DpInternal.h | 12 +++- datapath-windows/ovsext/Flow.c | 126 +++++++++++++++++++++++++++++++---- datapath-windows/ovsext/User.c | 19 ++++++ 4 files changed, 144 insertions(+), 16 deletions(-) (limited to 'datapath-windows') diff --git a/datapath-windows/ovsext/Actions.c b/datapath-windows/ovsext/Actions.c index 6922f0593..5c9b5c3a0 100644 --- a/datapath-windows/ovsext/Actions.c +++ b/datapath-windows/ovsext/Actions.c @@ -2057,6 +2057,9 @@ OvsDoExecuteActions(POVS_SWITCH_CONTEXT switchContext, goto dropit; } } + /* Reset vlan header info in flowkey. */ + key->l2.vlanKey.vlanTci = 0; + key->l2.vlanKey.vlanTpid = 0; break; } diff --git a/datapath-windows/ovsext/DpInternal.h b/datapath-windows/ovsext/DpInternal.h index 3e351b770..58e7ed8e2 100644 --- a/datapath-windows/ovsext/DpInternal.h +++ b/datapath-windows/ovsext/DpInternal.h @@ -112,6 +112,11 @@ typedef struct Icmp6Key { struct in6_addr ndTarget; /* IPv6 neighbor discovery (ND) target. */ } Icmp6Key; /* Size of 72 byte. */ +typedef struct VlanKey { + ovs_be16 vlanTci; /* If 802.1Q, TCI | VLAN_CFI; otherwise 0. */ + ovs_be16 vlanTpid; /* Vlan type. Generally 802.1q or 802.1ad.*/ +} VlanKey; + typedef struct L2Key { uint32_t inPort; /* Port number of input port. */ union { @@ -123,9 +128,10 @@ typedef struct L2Key { }; uint8_t dlSrc[6]; /* Ethernet source address. */ uint8_t dlDst[6]; /* Ethernet destination address. */ - ovs_be16 vlanTci; /* If 802.1Q, TCI | VLAN_CFI; otherwise 0. */ ovs_be16 dlType; /* Ethernet frame type. */ -} L2Key; /* Size of 24 byte. */ + struct VlanKey vlanKey; /* VLAN header. */ + uint16_t pad[3]; /* Padding 6 bytes. */ +} L2Key; /* Size of 32 byte. */ /* Number of packet attributes required to store OVS tunnel key. */ #define NUM_PKT_ATTR_REQUIRED 35 @@ -182,7 +188,7 @@ typedef struct MplsKey { typedef __declspec(align(8)) struct OvsFlowKey { OvsIPv4TunnelKey tunKey; /* 280 bytes */ - L2Key l2; /* 24 bytes */ + L2Key l2; /* 32 bytes */ union { /* These headers are mutually exclusive. */ IpKey ipKey; /* size 16 */ diff --git a/datapath-windows/ovsext/Flow.c b/datapath-windows/ovsext/Flow.c index f8809876e..7994786d2 100644 --- a/datapath-windows/ovsext/Flow.c +++ b/datapath-windows/ovsext/Flow.c @@ -115,7 +115,7 @@ const NL_POLICY nlFlowKeyPolicy[] = { [OVS_KEY_ATTR_PRIORITY] = {.type = NL_A_UNSPEC, .minLen = 4, .maxLen = 4, .optional = TRUE}, [OVS_KEY_ATTR_IN_PORT] = {.type = NL_A_UNSPEC, .minLen = 4, - .maxLen = 4, .optional = FALSE}, + .maxLen = 4, .optional = TRUE}, [OVS_KEY_ATTR_ETHERNET] = {.type = NL_A_UNSPEC, .minLen = sizeof(struct ovs_key_ethernet), .maxLen = sizeof(struct ovs_key_ethernet), @@ -457,6 +457,7 @@ _FlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx, NL_BUFFER nlBuf; PNL_ATTR keyAttrs[__OVS_KEY_ATTR_MAX]; PNL_ATTR tunnelAttrs[__OVS_TUNNEL_KEY_ATTR_MAX]; + PNL_ATTR encapAttrs[__OVS_KEY_ATTR_MAX]; NlBufInit(&nlBuf, usrParamsCtx->outputBuffer, usrParamsCtx->outputLength); @@ -464,6 +465,7 @@ _FlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx, RtlZeroMemory(&getOutput, sizeof(OvsFlowGetOutput)); UINT32 keyAttrOffset = 0; UINT32 tunnelKeyAttrOffset = 0; + UINT32 encapOffset = 0; BOOLEAN ok; NL_ERROR nlError = NL_ERROR_SUCCESS; @@ -503,6 +505,23 @@ _FlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx, goto done; } + if (keyAttrs[OVS_KEY_ATTR_ENCAP]) { + encapOffset = (UINT32)((PCHAR) (keyAttrs[OVS_KEY_ATTR_ENCAP]) + - (PCHAR)nlMsgHdr); + + if ((NlAttrParseNested(nlMsgHdr, encapOffset, + NlAttrLen(keyAttrs[OVS_KEY_ATTR_ENCAP]), + nlFlowKeyPolicy, + ARRAY_SIZE(nlFlowKeyPolicy), + encapAttrs, ARRAY_SIZE(encapAttrs))) + != TRUE) { + OVS_LOG_ERROR("Encap Key Attr Parsing failed for msg: %p", + nlMsgHdr); + rc = STATUS_INVALID_PARAMETER; + goto done; + } + } + if (keyAttrs[OVS_KEY_ATTR_TUNNEL]) { tunnelKeyAttrOffset = (UINT32)((PCHAR) (keyAttrs[OVS_KEY_ATTR_TUNNEL]) @@ -524,6 +543,12 @@ _FlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx, _MapKeyAttrToFlowPut(keyAttrs, tunnelAttrs, &(getInput.key)); + ASSERT(keyAttrs[OVS_KEY_ATTR_IN_PORT]); + + if (encapOffset) { + _MapKeyAttrToFlowPut(encapAttrs, tunnelAttrs, + &(getInput.key)); + } getInput.dpNo = ovsHdr->dp_ifindex; getInput.getFlags = FLOW_GET_STATS | FLOW_GET_ACTIONS; @@ -855,7 +880,7 @@ MapFlowKeyToNlKey(PNL_BUFFER nlBuf, { NTSTATUS rc = STATUS_SUCCESS; struct ovs_key_ethernet ethKey; - UINT32 offset = 0; + UINT32 offset = 0, encap_offset = 0; offset = NlMsgStartNested(nlBuf, keyType); if (!offset) { @@ -924,17 +949,34 @@ MapFlowKeyToNlKey(PNL_BUFFER nlBuf, } if (!NlMsgPutTailU16(nlBuf, OVS_KEY_ATTR_ETHERTYPE, - flowKey->l2.dlType)) { + flowKey->l2.vlanKey.vlanTci == 0 ? flowKey->l2.dlType : + flowKey->l2.vlanKey.vlanTpid)) { rc = STATUS_UNSUCCESSFUL; goto done; } - if (flowKey->l2.vlanTci) { + if (flowKey->l2.vlanKey.vlanTci || + flowKey->l2.dlType == ETH_TYPE_802_1PQ) { if (!NlMsgPutTailU16(nlBuf, OVS_KEY_ATTR_VLAN, - flowKey->l2.vlanTci)) { + flowKey->l2.vlanKey.vlanTci)) { + rc = STATUS_UNSUCCESSFUL; + goto done; + } + + /* Add encap attributes. */ + encap_offset = NlMsgStartNested(nlBuf, OVS_KEY_ATTR_ENCAP); + if (!encap_offset) { + /* Starting the nested attribute failed. */ rc = STATUS_UNSUCCESSFUL; goto done; } + + /* Add packet Ethernet Type*/ + if (!NlMsgPutTailU16(nlBuf, OVS_KEY_ATTR_ETHERTYPE, + flowKey->l2.dlType)) { + rc = STATUS_UNSUCCESSFUL; + goto encap; + } } /* ==== L3 + L4 ==== */ @@ -982,6 +1024,10 @@ MapFlowKeyToNlKey(PNL_BUFFER nlBuf, goto done; } } +encap: + if (encap_offset) { + NlMsgEndNested(nlBuf, encap_offset); + } done: NlMsgEndNested(nlBuf, offset); @@ -1336,9 +1382,11 @@ _MapNlToFlowPut(POVS_MESSAGE msgIn, PNL_ATTR keyAttr, UINT32 keyAttrOffset = (UINT32)((PCHAR)keyAttr - (PCHAR)nlMsgHdr); UINT32 tunnelKeyAttrOffset; + UINT32 encapOffset = 0; PNL_ATTR keyAttrs[__OVS_KEY_ATTR_MAX] = {NULL}; PNL_ATTR tunnelAttrs[__OVS_TUNNEL_KEY_ATTR_MAX] = {NULL}; + PNL_ATTR encapAttrs[__OVS_KEY_ATTR_MAX] = { NULL }; /* Get flow keys attributes */ if ((NlAttrParseNested(nlMsgHdr, keyAttrOffset, NlAttrLen(keyAttr), @@ -1351,6 +1399,23 @@ _MapNlToFlowPut(POVS_MESSAGE msgIn, PNL_ATTR keyAttr, goto done; } + if (keyAttrs[OVS_KEY_ATTR_ENCAP]) { + encapOffset = (UINT32)((PCHAR)(keyAttrs[OVS_KEY_ATTR_ENCAP]) + - (PCHAR)nlMsgHdr); + + if ((NlAttrParseNested(nlMsgHdr, encapOffset, + NlAttrLen(keyAttrs[OVS_KEY_ATTR_ENCAP]), + nlFlowKeyPolicy, + ARRAY_SIZE(nlFlowKeyPolicy), + encapAttrs, ARRAY_SIZE(encapAttrs))) + != TRUE) { + OVS_LOG_ERROR("Encap Key Attr Parsing failed for msg: %p", + nlMsgHdr); + rc = STATUS_INVALID_PARAMETER; + goto done; + } + } + if (keyAttrs[OVS_KEY_ATTR_TUNNEL]) { tunnelKeyAttrOffset = (UINT32)((PCHAR) (keyAttrs[OVS_KEY_ATTR_TUNNEL]) @@ -1372,6 +1437,12 @@ _MapNlToFlowPut(POVS_MESSAGE msgIn, PNL_ATTR keyAttr, _MapKeyAttrToFlowPut(keyAttrs, tunnelAttrs, &(mappedFlow->key)); + ASSERT(keyAttrs[OVS_KEY_ATTR_IN_PORT]); + + if (encapOffset) { + _MapKeyAttrToFlowPut(encapAttrs, tunnelAttrs, + &(mappedFlow->key)); + } /* Map the action */ if (actionAttr) { @@ -1469,7 +1540,9 @@ _MapKeyAttrToFlowPut(PNL_ATTR *keyAttrs, } /* ===== L2 headers ===== */ - destKey->l2.inPort = NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_IN_PORT]); + if (keyAttrs[OVS_KEY_ATTR_IN_PORT]) { + destKey->l2.inPort = NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_IN_PORT]); + } if (keyAttrs[OVS_KEY_ATTR_ETHERNET]) { const struct ovs_key_ethernet *eth_key; @@ -1488,7 +1561,11 @@ _MapKeyAttrToFlowPut(PNL_ATTR *keyAttrs, } if (keyAttrs[OVS_KEY_ATTR_VLAN]) { - destKey->l2.vlanTci = NlAttrGetU16(keyAttrs[OVS_KEY_ATTR_VLAN]); + destKey->l2.vlanKey.vlanTci = NlAttrGetU16(keyAttrs[OVS_KEY_ATTR_VLAN]); + if (destKey->l2.vlanKey.vlanTci != 0) { + /* set TPID to dlType. */ + destKey->l2.vlanKey.vlanTpid = destKey->l2.dlType; + } } /* ==== L3 + L4. ==== */ @@ -2267,17 +2344,20 @@ OvsExtractFlow(const NET_BUFFER_LIST *packet, if (vlanTagValue) { PNDIS_NET_BUFFER_LIST_8021Q_INFO vlanTag = (PNDIS_NET_BUFFER_LIST_8021Q_INFO)(PVOID *)&vlanTagValue; - flow->l2.vlanTci = htons(vlanTag->TagHeader.VlanId | OVSWIN_VLAN_CFI | - (vlanTag->TagHeader.UserPriority << 13)); + flow->l2.vlanKey.vlanTci = htons(vlanTag->TagHeader.VlanId | OVSWIN_VLAN_CFI | + (vlanTag->TagHeader.UserPriority << 13)); + flow->l2.vlanKey.vlanTpid = htons(ETH_TYPE_802_1PQ); } else { if (eth->dix.typeNBO == ETH_TYPE_802_1PQ_NBO) { Eth_802_1pq_Tag *tag= (Eth_802_1pq_Tag *)ð->dix.typeNBO; - flow->l2.vlanTci = ((UINT16)tag->priority << 13) | - OVSWIN_VLAN_CFI | - ((UINT16)tag->vidHi << 8) | tag->vidLo; + flow->l2.vlanKey.vlanTci = ((UINT16)tag->priority << 13) | + OVSWIN_VLAN_CFI | ((UINT16)tag->vidHi << 8) | tag->vidLo; + flow->l2.vlanKey.vlanTpid = htons(ETH_TYPE_802_1PQ); offset = sizeof (Eth_802_1pq_Tag); } else { - flow->l2.vlanTci = 0; + /* Initialize vlan key to 0 for non vlan packets. */ + flow->l2.vlanKey.vlanTci = 0; + flow->l2.vlanKey.vlanTpid = 0; } /* * XXX Please note after this point, src mac and dst mac should @@ -3095,7 +3175,9 @@ OvsProbeSupportedFeature(POVS_MESSAGE msgIn, PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg); UINT32 keyAttrOffset = (UINT32)((PCHAR)keyAttr - (PCHAR)nlMsgHdr); + UINT32 encapOffset = 0; PNL_ATTR keyAttrs[__OVS_KEY_ATTR_MAX] = { NULL }; + PNL_ATTR encapAttrs[__OVS_KEY_ATTR_MAX] = { NULL }; /* Get flow keys attributes */ if ((NlAttrParseNested(nlMsgHdr, keyAttrOffset, NlAttrLen(keyAttr), @@ -3108,6 +3190,24 @@ OvsProbeSupportedFeature(POVS_MESSAGE msgIn, goto done; } + if (keyAttrs[OVS_KEY_ATTR_ENCAP]) { + encapOffset = (UINT32)((PCHAR)(keyAttrs[OVS_KEY_ATTR_ENCAP]) + - (PCHAR)nlMsgHdr); + + /* Get tunnel keys attributes */ + if ((NlAttrParseNested(nlMsgHdr, encapOffset, + NlAttrLen(keyAttrs[OVS_KEY_ATTR_ENCAP]), + nlFlowKeyPolicy, + ARRAY_SIZE(nlFlowKeyPolicy), + encapAttrs, ARRAY_SIZE(encapAttrs))) + != TRUE) { + OVS_LOG_ERROR("Encap Key Attr Parsing failed for msg: %p", + nlMsgHdr); + status = STATUS_INVALID_PARAMETER; + goto done; + } + } + if (keyAttrs[OVS_KEY_ATTR_MPLS] && keyAttrs[OVS_KEY_ATTR_ETHERTYPE]) { ovs_be16 ethType = NlAttrGetU16(keyAttrs[OVS_KEY_ATTR_ETHERTYPE]); diff --git a/datapath-windows/ovsext/User.c b/datapath-windows/ovsext/User.c index 509472f23..b43d7cc04 100644 --- a/datapath-windows/ovsext/User.c +++ b/datapath-windows/ovsext/User.c @@ -321,6 +321,25 @@ OvsNlExecuteCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx, goto done; } + if (keyAttrs[OVS_KEY_ATTR_ENCAP]) { + UINT32 encapOffset = 0; + PNL_ATTR encapAttrs[__OVS_KEY_ATTR_MAX]; + encapOffset = (UINT32)((PCHAR)(keyAttrs[OVS_KEY_ATTR_ENCAP]) + - (PCHAR)nlMsgHdr); + + if ((NlAttrParseNested(nlMsgHdr, encapOffset, + NlAttrLen(keyAttrs[OVS_KEY_ATTR_ENCAP]), + nlFlowKeyPolicy, + nlFlowKeyPolicyLen, + encapAttrs, ARRAY_SIZE(encapAttrs))) + != TRUE) { + OVS_LOG_ERROR("Encap Key Attr Parsing failed for msg: %p", + nlMsgHdr); + status = STATUS_UNSUCCESSFUL; + goto done; + } + } + execute.dpNo = ovsHdr->dp_ifindex; _MapNlAttrToOvsPktExec(nlMsgHdr, nlAttrs, keyAttrs, &execute); -- cgit v1.2.1