[ovs-dev] Subject: [PATCH] Add support for 802.1ad (qinq)

Thomas F Herbert thomasfherbert at gmail.com
Wed Apr 2 16:07:11 UTC 2014


 From c7521a74f0e8f2673d4f542b885f6c82a0302f45 Mon Sep 17 00:00:00 2001
From: Tom Herbert <thomasfherbert at gmail.com>
Date: Wed, 2 Apr 2014 06:03:23 +0000
Add support for 802.1ad (qinq)
Allows 0x88a8 for TPID is S-VLAN (outer) tag.
Signed-off-by: Tom Herbert <thomasfherbert at gmail.com>

---
  NEWS                        |    1 +
  datapath/actions.c          |   12 ++++++++++--
  datapath/flow_netlink.c     |   15 +++++++++++++--
  include/linux/openvswitch.h |   12 ++++++------
  4 files changed, 30 insertions(+), 10 deletions(-)

diff --git a/NEWS b/NEWS
index 4f88e3b..201b0b6 100644
--- a/NEWS
+++ b/NEWS
@@ -13,6 +13,7 @@ Post-v2.1.0
     - Support for Linux kernels up to 3.12. On Kernel 3.12 OVS uses tunnel
       API for GRE and VXLAN.
     - Added DPDK support.
+   - Added support for 802.1qad


  v2.1.0 - xx xxx xxxx
diff --git a/datapath/actions.c b/datapath/actions.c
index 0b66e7c..91375d1 100644
--- a/datapath/actions.c
+++ b/datapath/actions.c
@@ -85,6 +85,7 @@ static int pop_vlan(struct sk_buff *skb)
          vlan_set_tci(skb, 0);
      } else {
          if (unlikely(skb->protocol != htons(ETH_P_8021Q) ||
+            skb->protocol != htons(ETH_P_8021AD) ||
                   skb->len < VLAN_ETH_HLEN))
              return 0;

@@ -101,7 +102,11 @@ static int pop_vlan(struct sk_buff *skb)
      if (unlikely(err))
          return err;

-    __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), ntohs(tci));
+        if (unlikely(skb->protocol == htons(ETH_P_8021AD)))
+        __vlan_put_tag(skb, htons(ETH_P_8021AD), ntohs(tci));
+        else
+        __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), ntohs(tci));
+
      return 0;
  }

@@ -121,7 +126,10 @@ static int push_vlan(struct sk_buff *skb, const 
struct ovs_action_push_vlan *vla
                      + (2 * ETH_ALEN), VLAN_HLEN, 0));

      }
-    __vlan_hwaccel_put_tag(skb, vlan->vlan_tpid, ntohs(vlan->vlan_tci) 
& ~VLAN_TAG_PRESENT);
+        if (likely(vlan->vlan_tpid == htons(ETH_P_8021Q)))
+        __vlan_hwaccel_put_tag(skb, vlan->vlan_tpid, 
ntohs(vlan->vlan_tci) & ~VLAN_TAG_PRESENT);
+        else
+        __vlan_put_tag(skb, vlan->vlan_tpid, ntohs(vlan->vlan_tci) & 
~VLAN_TAG_PRESENT);
      return 0;
  }

diff --git a/datapath/flow_netlink.c b/datapath/flow_netlink.c
index 5c32cd0..855af32 100644
--- a/datapath/flow_netlink.c
+++ b/datapath/flow_netlink.c
@@ -748,7 +748,8 @@ int ovs_nla_get_match(struct sw_flow_match *match,

      if ((key_attrs & (1ULL << OVS_KEY_ATTR_ETHERNET)) &&
          (key_attrs & (1ULL << OVS_KEY_ATTR_ETHERTYPE)) &&
-        (nla_get_be16(a[OVS_KEY_ATTR_ETHERTYPE]) == htons(ETH_P_8021Q))) {
+        ((nla_get_be16(a[OVS_KEY_ATTR_ETHERTYPE]) == htons(ETH_P_8021Q)) ||
+         (nla_get_be16(a[OVS_KEY_ATTR_ETHERTYPE]) == 
htons(ETH_P_8021AD)))) {
          __be16 tci;

          if (!((key_attrs & (1ULL << OVS_KEY_ATTR_VLAN)) &&
@@ -922,6 +923,15 @@ int ovs_nla_put_flow(const struct sw_flow_key *swkey,
          encap = nla_nest_start(skb, OVS_KEY_ATTR_ENCAP);
          if (!swkey->eth.tci)
              goto unencap;
+    } else if (swkey->eth.tci || swkey->eth.type == htons(ETH_P_8021AD)) {
+        __be16 eth_type;
+        eth_type = !is_mask ? htons(ETH_P_8021AD) : htons(0xffff);
+        if (nla_put_be16(skb, OVS_KEY_ATTR_ETHERTYPE, eth_type) ||
+            nla_put_be16(skb, OVS_KEY_ATTR_VLAN, output->eth.tci))
+            goto nla_put_failure;
+        encap = nla_nest_start(skb, OVS_KEY_ATTR_ENCAP);
+        if (!swkey->eth.tci)
+            goto unencap;
      } else
          encap = NULL;

@@ -1455,7 +1465,8 @@ int ovs_nla_copy_actions(const struct nlattr *attr,

          case OVS_ACTION_ATTR_PUSH_VLAN:
              vlan = nla_data(a);
-            if (vlan->vlan_tpid != htons(ETH_P_8021Q))
+            if ((vlan->vlan_tpid != htons(ETH_P_8021Q)) ||
+                (vlan->vlan_tpid != htons(ETH_P_8021AD)))
                  return -EINVAL;
              if (!(vlan->vlan_tci & htons(VLAN_TAG_PRESENT)))
                  return -EINVAL;
diff --git a/include/linux/openvswitch.h b/include/linux/openvswitch.h
index a88f6f1..5a82970 100644
--- a/include/linux/openvswitch.h
+++ b/include/linux/openvswitch.h
@@ -525,14 +525,14 @@ struct ovs_action_push_mpls {
   * @vlan_tci: Tag control identifier (TCI) to push.  The CFI bit must 
be set
   * (but it will not be set in the 802.1Q header that is pushed).
   *
- * The @vlan_tpid value is typically %ETH_P_8021Q.  The only acceptable 
TPID
- * values are those that the kernel module also parses as 802.1Q 
headers, to
+ * The @vlan_tpid value is typically %ETH_P_8021Q or %ETH_P_8021AD.  
The only acceptable
+ * TPID values are those that the kernel module also parses as 802.1Q 
headers, to
   * prevent %OVS_ACTION_ATTR_PUSH_VLAN followed by 
%OVS_ACTION_ATTR_POP_VLAN
   * from having surprising results.
   */
  struct ovs_action_push_vlan {
-    __be16 vlan_tpid;    /* 802.1Q TPID. */
-    __be16 vlan_tci;    /* 802.1Q TCI (VLAN ID and priority). */
+    __be16 vlan_tpid;    /* 802.1Q or 802.1ad TPID. */
+    __be16 vlan_tci;    /* 802.1Q or 802.1ad TCI (VLAN ID and priority). */
  };

  /* Data path hash algorithm for computing Datapath hash.
@@ -565,9 +565,9 @@ struct ovs_action_recirc {
   * @OVS_ACTION_ATTR_OUTPUT: Output packet to port.
   * @OVS_ACTION_ATTR_USERSPACE: Send packet to userspace according to 
nested
   * %OVS_USERSPACE_ATTR_* attributes.
- * @OVS_ACTION_ATTR_PUSH_VLAN: Push a new outermost 802.1Q header onto the
+ * @OVS_ACTION_ATTR_PUSH_VLAN: Push a new outermost 802.1Q or 802.1ad 
header onto the
   * packet.
- * @OVS_ACTION_ATTR_POP_VLAN: Pop the outermost 802.1Q header off the 
packet.
+ * @OVS_ACTION_ATTR_POP_VLAN: Pop the outermost 802.1Q or 802.1ad 
header off the packet.
   * @OVS_ACTION_ATTR_SAMPLE: Probabilitically executes actions, as 
specified in
   * the nested %OVS_SAMPLE_ATTR_* attributes.
   * @OVS_ACTION_ATTR_SET: Replaces the contents of an existing header.  The
-- 
1.7.10.4




More information about the dev mailing list