The openvswitch exchange the key with key netlink message
between the kernel data path and user space flow tables.
The key fields are defined as key attributes.

Signed-off-by: Johnson Li <johnson...@intel.com>

diff --git a/datapath/flow_netlink.c b/datapath/flow_netlink.c
index 6ffcc53..15685c7 100644
--- a/datapath/flow_netlink.c
+++ b/datapath/flow_netlink.c
@@ -147,6 +147,13 @@ static bool match_validate(const struct sw_flow_match 
*match,
                       | (1ULL << OVS_KEY_ATTR_IN_PORT)
                       | (1ULL << OVS_KEY_ATTR_ETHERTYPE));
 
+       /* Network Service Header */
+       if (match->key->nsh.md_type) {
+               key_expected |= 1 << OVS_KEY_ATTR_NSH;
+               if (match->mask)
+                       mask_allowed |= 1 << OVS_KEY_ATTR_NSH;
+       }
+
        /* Check key attributes. */
        if (match->key->eth.type == htons(ETH_P_ARP)
                        || match->key->eth.type == htons(ETH_P_RARP)) {
@@ -279,12 +286,25 @@ size_t ovs_tun_key_attr_size(void)
                + nla_total_size(2);   /* OVS_TUNNEL_KEY_ATTR_TP_DST */
 }
 
+size_t ovs_nsh_key_attr_size(void)
+{
+       return    nla_total_size(1)    /* OVS_NSH_KEY_ATTR_FLAGS */
+               + nla_total_size(1)    /* OVS_NSH_KEY_ATTR_MD_TYPE */
+               + nla_total_size(1)    /* OVS_NSH_KEY_ATTR_NEXT_PROTO */
+               + nla_total_size(1)    /* OVS_NSH_KEY_ATTR_NSI */
+               + nla_total_size(4)    /* OVS_NSH_KEY_ATTR_NSP */
+               + nla_total_size(4)    /* OVS_NSH_KEY_ATTR_NSHC1 */
+               + nla_total_size(4)    /* OVS_NSH_KEY_ATTR_NSHC2 */
+               + nla_total_size(4)    /* OVS_NSH_KEY_ATTR_NSHC3 */
+               + nla_total_size(4);   /* OVS_NSH_KEY_ATTR_NSHC4 */
+}
+
 size_t ovs_key_attr_size(void)
 {
        /* Whenever adding new OVS_KEY_ FIELDS, we should consider
         * updating this function.
         */
-       BUILD_BUG_ON(OVS_KEY_ATTR_TUNNEL_INFO != 26);
+       BUILD_BUG_ON(OVS_KEY_ATTR_TUNNEL_INFO != 27);
 
        return    nla_total_size(4)   /* OVS_KEY_ATTR_PRIORITY */
                + nla_total_size(0)   /* OVS_KEY_ATTR_TUNNEL */
@@ -300,6 +320,8 @@ size_t ovs_key_attr_size(void)
                + nla_total_size(12)  /* OVS_KEY_ATTR_ETHERNET */
                + nla_total_size(2)   /* OVS_KEY_ATTR_ETHERTYPE */
                + nla_total_size(4)   /* OVS_KEY_ATTR_VLAN */
+               + nla_total_size(0)   /* OVS_KEY_ATTR_NSH */
+               + ovs_nsh_key_attr_size()
                + nla_total_size(0)   /* OVS_KEY_ATTR_ENCAP */
                + nla_total_size(2)   /* OVS_KEY_ATTR_ETHERTYPE */
                + nla_total_size(40)  /* OVS_KEY_ATTR_IPV6 */
@@ -327,6 +349,18 @@ static const struct ovs_len_tbl 
ovs_tunnel_key_lens[OVS_TUNNEL_KEY_ATTR_MAX + 1]
                                                .next = ovs_vxlan_ext_key_lens 
},
 };
 
+static const struct ovs_len_tbl ovs_nsh_key_lens[OVS_NSH_KEY_ATTR_MAX + 1] = {
+       [OVS_NSH_KEY_ATTR_FLAGS]            = { .len = 1 },
+       [OVS_NSH_KEY_ATTR_MD_TYPE]          = { .len = 1 },
+       [OVS_NSH_KEY_ATTR_NEXT_PROTO]       = { .len = 1 },
+       [OVS_NSH_KEY_ATTR_NSI]              = { .len = 1 },
+       [OVS_NSH_KEY_ATTR_NSP]              = { .len = 4 },
+       [OVS_NSH_KEY_ATTR_NSHC1]            = { .len = 4 },
+       [OVS_NSH_KEY_ATTR_NSHC2]            = { .len = 4 },
+       [OVS_NSH_KEY_ATTR_NSHC3]            = { .len = 4 },
+       [OVS_NSH_KEY_ATTR_NSHC4]            = { .len = 4 },
+};
+
 /* The size of the argument for each %OVS_KEY_ATTR_* Netlink attribute.  */
 static const struct ovs_len_tbl ovs_key_lens[OVS_KEY_ATTR_MAX + 1] = {
        [OVS_KEY_ATTR_ENCAP]     = { .len = OVS_ATTR_NESTED },
@@ -335,6 +369,8 @@ static const struct ovs_len_tbl 
ovs_key_lens[OVS_KEY_ATTR_MAX + 1] = {
        [OVS_KEY_ATTR_SKB_MARK]  = { .len = sizeof(u32) },
        [OVS_KEY_ATTR_ETHERNET]  = { .len = sizeof(struct ovs_key_ethernet) },
        [OVS_KEY_ATTR_VLAN]      = { .len = sizeof(__be16) },
+       [OVS_KEY_ATTR_NSH]       = { .len = OVS_ATTR_NESTED,
+                                    .next = ovs_nsh_key_lens, },
        [OVS_KEY_ATTR_ETHERTYPE] = { .len = sizeof(__be16) },
        [OVS_KEY_ATTR_IPV4]      = { .len = sizeof(struct ovs_key_ipv4) },
        [OVS_KEY_ATTR_IPV6]      = { .len = sizeof(struct ovs_key_ipv6) },
@@ -853,6 +889,151 @@ static int metadata_from_nlattrs(struct net *net, struct 
sw_flow_match *match,
        return 0;
 }
 
+static int nsh_from_nlattr(const struct nlattr *attr,
+                          struct sw_flow_match *match, bool is_mask,
+                          bool log)
+{
+       struct nlattr *a;
+       int rem;
+
+       nla_for_each_nested(a, attr, rem) {
+               int type = nla_type(a);
+
+               if (type > OVS_NSH_KEY_ATTR_MAX) {
+                       OVS_NLERR(log, "NSH attr %d out of range max %d",
+                                 type, OVS_NSH_KEY_ATTR_MAX);
+                       return -EINVAL;
+               }
+
+               if (!check_attr_len(nla_len(a),
+                                   ovs_nsh_key_lens[type].len)) {
+                       OVS_NLERR(log, "NSH attr %d has unexpected len %d",
+                                 type, nla_len(a));
+                       return -EINVAL;
+               }
+
+               switch (type) {
+               case OVS_NSH_KEY_ATTR_FLAGS:
+                       SW_FLOW_KEY_PUT(match, nsh.flags,
+                                       nla_get_u8(a), is_mask);
+                       break;
+               case OVS_NSH_KEY_ATTR_MD_TYPE:
+                       SW_FLOW_KEY_PUT(match, nsh.md_type,
+                                       nla_get_u8(a), is_mask);
+                       break;
+               case OVS_NSH_KEY_ATTR_NEXT_PROTO:
+                       SW_FLOW_KEY_PUT(match, nsh.next_proto,
+                                       nla_get_u8(a), is_mask);
+                       break;
+               case OVS_NSH_KEY_ATTR_NSI:
+                       SW_FLOW_KEY_PUT(match, nsh.nsi,
+                                       nla_get_u8(a), is_mask);
+                       break;
+               case OVS_NSH_KEY_ATTR_NSP:
+                       SW_FLOW_KEY_PUT(match, nsh.nsp,
+                                       nla_get_be32(a), is_mask);
+                       break;
+               case OVS_NSH_KEY_ATTR_NSHC1:
+                       SW_FLOW_KEY_PUT(match, nsh.nshc1,
+                                       nla_get_be32(a), is_mask);
+                       break;
+               case OVS_NSH_KEY_ATTR_NSHC2:
+                       SW_FLOW_KEY_PUT(match, nsh.nshc2,
+                                       nla_get_be32(a), is_mask);
+                       break;
+               case OVS_NSH_KEY_ATTR_NSHC3:
+                       SW_FLOW_KEY_PUT(match, nsh.nshc3,
+                                       nla_get_be32(a), is_mask);
+                       break;
+               case OVS_NSH_KEY_ATTR_NSHC4:
+                       SW_FLOW_KEY_PUT(match, nsh.nshc4,
+                                       nla_get_be32(a), is_mask);
+                       break;
+               default:
+                       OVS_NLERR(log, "Unknown NSH attribute %d",
+                                 type);
+                       return -EINVAL;
+               }
+       }
+
+       if (rem > 0) {
+               OVS_NLERR(log, "NSH attribute has %d unknown bytes.",
+                         rem);
+               return -EINVAL;
+       }
+
+       if (!is_mask) {
+               if (!match->key->nsh.md_type) {
+                       OVS_NLERR(log, "NSH Header MD Type is zero");
+                       return -EINVAL;
+               }
+       }
+
+       return 0;
+}
+
+static int __nsh_to_nlattr(struct sk_buff *skb,
+                          const struct ovs_nsh_key *output)
+{
+       if (output->md_type) {
+               if (output->flags &&
+                   nla_put_u8(skb, OVS_NSH_KEY_ATTR_FLAGS,
+                              output->flags))
+                       return -EMSGSIZE;
+               if (nla_put_u8(skb, OVS_NSH_KEY_ATTR_MD_TYPE,
+                              output->md_type))
+                       return -EMSGSIZE;
+               if (output->next_proto &&
+                   nla_put_u8(skb, OVS_NSH_KEY_ATTR_NEXT_PROTO,
+                              output->next_proto))
+                       return -EMSGSIZE;
+               if (output->nsi &&
+                   nla_put_u8(skb, OVS_NSH_KEY_ATTR_NSI,
+                              output->nsi))
+                       return -EMSGSIZE;
+               if (output->nsp &&
+                   nla_put_be32(skb, OVS_NSH_KEY_ATTR_NSP,
+                                output->nsp))
+                       return -EMSGSIZE;
+               if (output->nshc1 &&
+                   nla_put_be32(skb, OVS_NSH_KEY_ATTR_NSHC1,
+                                output->nshc1))
+                       return -EMSGSIZE;
+               if (output->nshc2 &&
+                   nla_put_be32(skb, OVS_NSH_KEY_ATTR_NSHC2,
+                                output->nshc2))
+                       return -EMSGSIZE;
+               if (output->nshc3 &&
+                   nla_put_be32(skb, OVS_NSH_KEY_ATTR_NSHC3,
+                                output->nshc3))
+                       return -EMSGSIZE;
+               if (output->nshc4 &&
+                   nla_put_be32(skb, OVS_NSH_KEY_ATTR_NSHC4,
+                                output->nshc4))
+                       return -EMSGSIZE;
+       }
+
+       return 0;
+}
+
+static int nsh_to_nlattr(struct sk_buff *skb,
+                        const struct ovs_nsh_key *output)
+{
+       struct nlattr *nla;
+       int err;
+
+       nla = nla_nest_start(skb, OVS_KEY_ATTR_NSH);
+       if (!nla)
+               return -EMSGSIZE;
+
+       err = __nsh_to_nlattr(skb, output);
+       if (err)
+               return err;
+
+       nla_nest_end(skb, nla);
+       return 0;
+}
+
 static int ovs_key_from_nlattrs(struct net *net, struct sw_flow_match *match,
                                u64 attrs, const struct nlattr **a,
                                bool is_mask, bool log)
@@ -863,6 +1044,14 @@ static int ovs_key_from_nlattrs(struct net *net, struct 
sw_flow_match *match,
        if (err)
                return err;
 
+       if (attrs & (1 << OVS_KEY_ATTR_NSH)) {
+               if (nsh_from_nlattr(a[OVS_KEY_ATTR_NSH], match,
+                                   is_mask, log) < 0) {
+                       return -EINVAL;
+               }
+               attrs &= ~(1 << OVS_KEY_ATTR_NSH);
+       }
+
        if (attrs & (1ULL << OVS_KEY_ATTR_ETHERNET)) {
                const struct ovs_key_ethernet *eth_key;
 
@@ -1391,6 +1580,11 @@ static int __ovs_nla_put_key(const struct sw_flow_key 
*swkey,
                        goto nla_put_failure;
        }
 
+       if ((swkey->nsh.md_type)) {
+               if (nsh_to_nlattr(skb, &output->nsh))
+                       goto nla_put_failure;
+       }
+
        if (swkey->phy.in_port == DP_MAX_PORTS) {
                if (is_mask && (output->phy.in_port == 0xffff))
                        if (nla_put_u32(skb, OVS_KEY_ATTR_IN_PORT, 0xffffffff))
diff --git a/datapath/linux/compat/include/linux/openvswitch.h 
b/datapath/linux/compat/include/linux/openvswitch.h
index bd37594..6cde92a 100644
--- a/datapath/linux/compat/include/linux/openvswitch.h
+++ b/datapath/linux/compat/include/linux/openvswitch.h
@@ -341,6 +341,7 @@ enum ovs_key_attr {
        OVS_KEY_ATTR_ND,        /* struct ovs_key_nd */
        OVS_KEY_ATTR_SKB_MARK,  /* u32 skb mark */
        OVS_KEY_ATTR_TUNNEL,    /* Nested set of ovs_tunnel attributes */
+       OVS_KEY_ATTR_NSH,       /* Nested set of ovs_nsh attributes */
        OVS_KEY_ATTR_SCTP,      /* struct ovs_key_sctp */
        OVS_KEY_ATTR_TCP_FLAGS, /* be16 TCP flags. */
        OVS_KEY_ATTR_DP_HASH,   /* u32 hash value. Value 0 indicates the hash
@@ -383,6 +384,21 @@ enum ovs_tunnel_key_attr {
 
 #define OVS_TUNNEL_KEY_ATTR_MAX (__OVS_TUNNEL_KEY_ATTR_MAX - 1)
 
+enum ovs_nsh_key_attr {
+       OVS_NSH_KEY_ATTR_FLAGS,                 /* u8 NSH header flags */
+       OVS_NSH_KEY_ATTR_MD_TYPE,               /* u8 Metadata Type */
+       OVS_NSH_KEY_ATTR_NEXT_PROTO,            /* u8 Next Protocol */
+       OVS_NSH_KEY_ATTR_NSI,                   /* u8 Service Index */
+       OVS_NSH_KEY_ATTR_NSP,                   /* be32 Service Path ID */
+       OVS_NSH_KEY_ATTR_NSHC1,                 /* be32 NSH Context Header 1 */
+       OVS_NSH_KEY_ATTR_NSHC2,                 /* be32 NSH Context Header 2 */
+       OVS_NSH_KEY_ATTR_NSHC3,                 /* be32 NSH Context Header 3 */
+       OVS_NSH_KEY_ATTR_NSHC4,                 /* be32 NSH Context Header 4 */
+       __OVS_NSH_KEY_ATTR_MAX
+};
+
+#define OVS_NSH_KEY_ATTR_MAX (__OVS_NSH_KEY_ATTR_MAX - 1)
+
 /**
  * enum ovs_frag_type - IPv4 and IPv6 fragment type
  * @OVS_FRAG_TYPE_NONE: Packet is not a fragment.
diff --git a/lib/odp-execute.c b/lib/odp-execute.c
index 4239624..2de81dc 100644
--- a/lib/odp-execute.c
+++ b/lib/odp-execute.c
@@ -336,6 +336,7 @@ odp_execute_set_action(struct dp_packet *packet, const 
struct nlattr *a)
     case OVS_KEY_ATTR_CT_ZONE:
     case OVS_KEY_ATTR_CT_MARK:
     case OVS_KEY_ATTR_CT_LABELS:
+    case OVS_KEY_ATTR_NSH: /* Not support SET command for this version */
     case __OVS_KEY_ATTR_MAX:
     default:
         OVS_NOT_REACHED();
@@ -435,6 +436,7 @@ odp_execute_masked_set_action(struct dp_packet *packet,
     case OVS_KEY_ATTR_ICMP:
     case OVS_KEY_ATTR_ICMPV6:
     case OVS_KEY_ATTR_TCP_FLAGS:
+    case OVS_KEY_ATTR_NSH: /* Not support SET command for this version */
     case __OVS_KEY_ATTR_MAX:
     default:
         OVS_NOT_REACHED();
diff --git a/ofproto/ofproto-dpif-sflow.c b/ofproto/ofproto-dpif-sflow.c
index fbc82b7..982e676 100644
--- a/ofproto/ofproto-dpif-sflow.c
+++ b/ofproto/ofproto-dpif-sflow.c
@@ -1036,6 +1036,7 @@ sflow_read_set_action(const struct nlattr *attr,
     case OVS_KEY_ATTR_CT_MARK:
     case OVS_KEY_ATTR_CT_LABELS:
     case OVS_KEY_ATTR_UNSPEC:
+    case OVS_KEY_ATTR_NSH: /* Not support SET command for this version */
     case __OVS_KEY_ATTR_MAX:
     default:
         break;
-- 
1.8.4.2

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to