From patchwork Fri Jan 11 00:45:24 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anand Kumar X-Patchwork-Id: 1023310 X-Patchwork-Delegate: aserdean@cloudbasesolutions.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=vmware.com Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 43bPLL0fRnz9sCh for ; Fri, 11 Jan 2019 11:46:02 +1100 (AEDT) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id ABA7816E5; Fri, 11 Jan 2019 00:46:00 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 2ED8B16DF for ; Fri, 11 Jan 2019 00:45:59 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from EX13-EDG-OU-002.vmware.com (ex13-edg-ou-002.vmware.com [208.91.0.190]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id F0C1A84E for ; Fri, 11 Jan 2019 00:45:57 +0000 (UTC) Received: from sc9-mailhost3.vmware.com (10.113.161.73) by EX13-EDG-OU-002.vmware.com (10.113.208.156) with Microsoft SMTP Server id 15.0.1156.6; Thu, 10 Jan 2019 16:45:54 -0800 Received: from WIN-ANAND1.vmware.com (win-anand1.prom.eng.vmware.com [10.33.79.212]) by sc9-mailhost3.vmware.com (Postfix) with ESMTP id D208B40D6D; Thu, 10 Jan 2019 16:45:56 -0800 (PST) From: Anand Kumar To: Date: Thu, 10 Jan 2019 16:45:24 -0800 Message-ID: <20190111004524.7868-1-kumaranand@vmware.com> X-Mailer: git-send-email 2.9.3.windows.1 MIME-Version: 1.0 Received-SPF: None (EX13-EDG-OU-002.vmware.com: kumaranand@vmware.com does not designate permitted sender hosts) X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH] datapath-windows: Add support for 'OVS_KEY_ATTR_ENCAP' key attribute. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org 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 --- 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(-) diff --git a/datapath-windows/ovsext/Actions.c b/datapath-windows/ovsext/Actions.c index 6922f05..5c9b5c3 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 3e351b7..58e7ed8 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 f880987..7994786 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 509472f..b43d7cc 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);