[ovs-dev] [RFC PATCH v2 06/13] Parse NSH header in function flow_extract in user space

Johnson Li johnson.li at intel.com
Tue Jul 12 17:27:53 UTC 2016


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

diff --git a/lib/flow.c b/lib/flow.c
index a4c1215..cdeccfc 100644
--- a/lib/flow.c
+++ b/lib/flow.c
@@ -439,6 +439,46 @@ invalid:
     arp_buf[1] = eth_addr_zero;
 }
 
+static int
+parse_nsh(const void **datap, size_t *sizep,
+          struct flow_nsh *key, struct tun_metadata *md OVS_UNUSED)
+{
+    const struct nsh_header *nsh = (const struct nsh_header *) *datap;
+    uint16_t length = 0;
+
+    memset(key, 0, sizeof(struct flow_nsh));
+
+    length = nsh->base.length << 2;
+    if (length > NSH_LEN_MAX)
+        return -EINVAL;
+
+    key->flags = nsh->base.flags;
+    key->md_type = nsh->base.md_type;
+    key->next_proto = nsh->base.next_proto;
+    key->nsi = nsh->base.nsi;
+    key->nsp = nsh->base.sfp << 8;
+
+    if (nsh->base.md_type == NSH_MD_TYPE1) {
+        const struct nsh_md1_ctx *ctx = (struct nsh_md1_ctx *)(nsh + 1);
+        key->nshc1 = ctx->nshc1;
+        key->nshc2 = ctx->nshc2;
+        key->nshc3 = ctx->nshc3;
+        key->nshc4 = ctx->nshc4;
+#if 0
+    } else if (nsh->base.md_type == NSH_MD_TYPE2) {
+        const struct nsh_md2_ctx *ctx = (struct nsh_md2_ctx *)(nsh + 1);
+
+        /* Prototype with TUN_METADATA APIs. */
+        tun_metadata_from_nsh_ctx((struct geneve_opt *)ctx,
+                                   md, length - sizeof *nsh);
+#endif
+    }
+
+    data_pull(datap, sizep, length);
+
+    return 0;
+}
+
 /* Initializes 'flow' members from 'packet' and 'md'
  *
  * Initializes 'packet' header l2 pointer to the start of the Ethernet
@@ -563,6 +603,27 @@ miniflow_extract(struct dp_packet *packet, struct miniflow *dst)
     /* Network layer. */
     packet->l3_ofs = (char *)data - l2;
 
+    /* Network Service Header */
+    if (dl_type == htons(ETH_TYPE_NSH)) {
+        struct flow_nsh nsh;
+        struct tun_metadata metadata;
+
+        if (OVS_LIKELY(!parse_nsh(&data, &size, &nsh, &metadata))) {
+            miniflow_push_words(mf, nsh, &nsh, sizeof(struct flow_nsh) /
+                                sizeof(uint64_t));
+#if 0
+            if (nsh.md_type == NSH_MD_TYPE2) {
+                /* MD type 2 is not fully implemented yet. */
+                if (metadata.present.map) {
+                    miniflow_push_words(mf, tunnel.metadata, &metadata,
+                                        sizeof(metadata) / sizeof(uint64_t));
+                }
+            }
+#endif
+        }
+        goto out;
+    }
+
     nw_frag = 0;
     if (OVS_LIKELY(dl_type == htons(ETH_TYPE_IP))) {
         const struct ip_header *nh = data;
@@ -1293,6 +1354,18 @@ void flow_wildcards_init_for_packet(struct flow_wildcards *wc,
     WC_MASK_FIELD(wc, dp_hash);
     WC_MASK_FIELD(wc, in_port);
 
+    if (flow->nsh.nsp) {
+        WC_MASK_FIELD(wc, nsh.flags);
+        WC_MASK_FIELD(wc, nsh.md_type);
+        WC_MASK_FIELD(wc, nsh.next_proto);
+        WC_MASK_FIELD(wc, nsh.nsi);
+        WC_MASK_FIELD(wc, nsh.nsp);
+        WC_MASK_FIELD(wc, nsh.nshc1);
+        WC_MASK_FIELD(wc, nsh.nshc2);
+        WC_MASK_FIELD(wc, nsh.nshc3);
+        WC_MASK_FIELD(wc, nsh.nshc4);
+    }
+
     /* actset_output wildcarded. */
 
     WC_MASK_FIELD(wc, dl_dst);
@@ -1397,6 +1470,18 @@ flow_wc_map(const struct flow *flow, struct flowmap *map)
     FLOWMAP_SET(map, ct_mark);
     FLOWMAP_SET(map, ct_label);
 
+    if (flow->nsh.nsp) {
+        FLOWMAP_SET(map, nsh.flags);
+        FLOWMAP_SET(map, nsh.md_type);
+        FLOWMAP_SET(map, nsh.next_proto);
+        FLOWMAP_SET(map, nsh.nsi);
+        FLOWMAP_SET(map, nsh.nsp);
+        FLOWMAP_SET(map, nsh.nshc1);
+        FLOWMAP_SET(map, nsh.nshc2);
+        FLOWMAP_SET(map, nsh.nshc3);
+        FLOWMAP_SET(map, nsh.nshc4);
+    }
+
     /* Ethertype-dependent fields. */
     if (OVS_LIKELY(flow->dl_type == htons(ETH_TYPE_IP))) {
         FLOWMAP_SET(map, nw_src);
diff --git a/lib/packets.h b/lib/packets.h
index 5945940..6b3e2ae 100644
--- a/lib/packets.h
+++ b/lib/packets.h
@@ -334,6 +334,7 @@ ovs_be32 set_mpls_lse_values(uint8_t ttl, uint8_t tc, uint8_t bos,
 #define ETH_TYPE_RARP          0x8035
 #define ETH_TYPE_MPLS          0x8847
 #define ETH_TYPE_MPLS_MCAST    0x8848
+#define ETH_TYPE_NSH           0x894F
 
 static inline bool eth_type_mpls(ovs_be16 eth_type)
 {
@@ -1018,6 +1019,53 @@ struct vxlanhdr {
 
 #define VXLAN_FLAGS 0x08000000  /* struct vxlanhdr.vx_flags required value. */
 
+/* Network service header */
+struct nsh_base_hdr {
+    uint8_t flags;
+    uint8_t length;
+    uint8_t md_type;
+    uint8_t next_proto;
+    union {
+        struct {
+            uint8_t nsp[3];
+            uint8_t nsi;
+        };
+        ovs_be32 sfp;
+    };
+};
+
+struct nsh_md1_ctx {
+    ovs_be32 nshc1;
+    ovs_be32 nshc2;
+    ovs_be32 nshc3;
+    ovs_be32 nshc4;
+};
+
+struct nsh_md2_ctx {
+    ovs_be16 md_class;
+    uint8_t type;
+    uint8_t length;
+    uint8_t md_value[];
+};
+
+struct nsh_header {
+    struct nsh_base_hdr base;
+    uint8_t ctx[];
+};
+
+#define NSH_P_IPV4        0x01
+#define NSH_P_IPV6        0x02
+#define NSH_P_ETHERNET    0x03
+
+#define NSH_MD_TYPE_NONE  0x00
+#define NSH_MD_TYPE1      0x01
+#define NSH_MD_TYPE2      0x02
+#define NSH_MD_EXP1       0xFE
+#define NSH_MD_EXP2       0xFF
+
+#define NSH_TYPE1_LEN     24
+#define NSH_LEN_MAX       256
+
 void ipv6_format_addr(const struct in6_addr *addr, struct ds *);
 void ipv6_format_addr_bracket(const struct in6_addr *addr, struct ds *,
                               bool bracket);
-- 
1.8.4.2

--------------------------------------------------------------
Intel Research and Development Ireland Limited
Registered in Ireland
Registered Office: Collinstown Industrial Park, Leixlip, County Kildare
Registered Number: 308263


This e-mail and any attachments may contain confidential material for the sole
use of the intended recipient(s). Any review or distribution by others is
strictly prohibited. If you are not the intended recipient, please contact the
sender and delete all copies.




More information about the dev mailing list