diff mbox series

[ovs-dev] datapath-windows: Add support for 'OVS_KEY_ATTR_ENCAP' key attribute.

Message ID 20190111004524.7868-1-kumaranand@vmware.com
State Accepted
Delegated to: Alin Gabriel Serdean
Headers show
Series [ovs-dev] datapath-windows: Add support for 'OVS_KEY_ATTR_ENCAP' key attribute. | expand

Commit Message

Anand Kumar Jan. 11, 2019, 12:45 a.m. UTC
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 <kumaranand@vmware.com>
---
 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(-)

Comments

Alin-Gabriel Serdean Jan. 22, 2019, 6:03 p.m. UTC | #1
> -----Mesaj original-----
> De la: ovs-dev-bounces@openvswitch.org <ovs-dev-
> bounces@openvswitch.org> În numele Anand Kumar
> Trimis: Friday, January 11, 2019 2:45 AM
> Către: dev@openvswitch.org
> Subiect: [ovs-dev] [PATCH] 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 <kumaranand@vmware.com>
> ---
>  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(-)
> 
[Alin Serdean] 

Thanks for the patch!
Acked-by: Alin Gabriel Serdean <aserdean@ovn.org>
Alin-Gabriel Serdean Jan. 28, 2019, 1:40 p.m. UTC | #2
> > -----Mesaj original-----
> > De la: ovs-dev-bounces@openvswitch.org <ovs-dev-
> > bounces@openvswitch.org> În numele Anand Kumar
> > Trimis: Friday, January 11, 2019 2:45 AM
> > Către: dev@openvswitch.org
> > Subiect: [ovs-dev] [PATCH] 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 <kumaranand@vmware.com>
> > ---
> >  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(-)
> >
> [Alin Serdean]
> 
> Thanks for the patch!
> Acked-by: Alin Gabriel Serdean <aserdean@ovn.org>
> 
Applied on master and branch-2.11
diff mbox series

Patch

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 *)&eth->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);