Parse the Network Service Header to fullfill the fields in the
struct sw_flow_key.

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

diff --git a/datapath/flow.c b/datapath/flow.c
index fd09cec..debac6f 100644
--- a/datapath/flow.c
+++ b/datapath/flow.c
@@ -44,6 +44,7 @@
 #include <net/ipv6.h>
 #include <net/mpls.h>
 #include <net/ndisc.h>
+#include <net/nsh.h>
 
 #include "datapath.h"
 #include "conntrack.h"
@@ -296,6 +297,45 @@ static bool icmp6hdr_ok(struct sk_buff *skb)
                                  sizeof(struct icmp6hdr));
 }
 
+static int parse_nsh(struct sk_buff *skb, struct sw_flow_key *key)
+{
+       struct nsh_hdr *nsh_hdr = (struct nsh_hdr *)skb_mac_header(skb);
+       uint16_t retval = -1;
+       // uint16_t length = 0; /* For MD type 2 support */
+
+       retval = nsh_hdr->base.length << 2;
+       if (retval > NSH_LEN_MAX)
+               return -EINVAL;
+
+       key->nsh.md_type = nsh_hdr->base.md_type;
+       key->nsh.next_proto = nsh_hdr->base.next_proto;
+       key->nsh.nsi = nsh_hdr->base.svc_idx;
+       key->nsh.nsp = nsh_hdr->base.path_hdr << 8;
+
+       if (nsh_hdr->base.md_type == NSH_M_TYPE1) {
+               struct nsh_md1_ctx *ctx = (struct nsh_md1_ctx *)(nsh_hdr->ctx);
+
+               key->nsh.nshc1 = ctx->nshc1;
+               key->nsh.nshc2 = ctx->nshc2;
+               key->nsh.nshc3 = ctx->nshc3;
+               key->nsh.nshc4 = ctx->nshc4;
+#if 0
+        } else if (nsh_hdr->base.md_type == NSH_M_TYPE2) {
+               /* Todo: Add full support for MD type 2.
+                 * Just prototype with TUN_METADATA APIs here.
+                 */
+               struct nsh_md2_ctx *ctx = (struct nsh_md2_ctx *)(nsh_hdr->ctx);
+               length = retval - sizeof *nsh_hdr;
+
+               memcpy(TUN_METADATA_OPTS(key, length), ctx, length);
+               key->tun_opts_len = length;
+#endif
+        }
+
+       __skb_pull(skb, retval);
+       return retval;
+}
+
 static int parse_vlan(struct sk_buff *skb, struct sw_flow_key *key)
 {
        struct qtag_prefix {
@@ -454,7 +494,7 @@ invalid:
  */
 static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
 {
-       int error;
+       int error, nsh_len = -1;
        struct ethhdr *eth;
 
        /* Flags are always used as part of stats */
@@ -491,6 +531,11 @@ static int key_extract(struct sk_buff *skb, struct 
sw_flow_key *key)
 
        /* Network Service Header */
        memset(&key->nsh, 0, sizeof(key->nsh));
+       if (key->eth.type == htons(ETH_P_NSH)) {
+               nsh_len = parse_nsh(skb, key);
+               if (unlikely(nsh_len < 0))
+                       return -EINVAL;
+       }
 
        /* Network layer. */
        if (key->eth.type == htons(ETH_P_IP)) {
@@ -679,6 +724,11 @@ static int key_extract(struct sk_buff *skb, struct 
sw_flow_key *key)
                        }
                }
        }
+
+       if (nsh_len > 0) {
+               __skb_push(skb, nsh_len);
+       }
+
        return 0;
 }
 
diff --git a/datapath/linux/Modules.mk b/datapath/linux/Modules.mk
index d6ec06a..155cdbc 100644
--- a/datapath/linux/Modules.mk
+++ b/datapath/linux/Modules.mk
@@ -93,6 +93,7 @@ openvswitch_headers += \
        linux/compat/include/net/stt.h \
        linux/compat/include/net/vrf.h \
        linux/compat/include/net/vxlan.h \
+       linux/compat/include/net/nsh.h \
        linux/compat/include/net/netfilter/nf_conntrack.h \
        linux/compat/include/net/netfilter/nf_conntrack_core.h \
        linux/compat/include/net/netfilter/nf_conntrack_expect.h \
diff --git a/datapath/linux/compat/include/net/nsh.h 
b/datapath/linux/compat/include/net/nsh.h
new file mode 100644
index 0000000..00cab48
--- /dev/null
+++ b/datapath/linux/compat/include/net/nsh.h
@@ -0,0 +1,125 @@
+#ifndef __NET_NSH_H
+#define __NET_NSH_H 1
+
+#include <asm/byteorder.h>
+
+/*
+ * Network Service Header:
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |Ver|O|C|R|R|R|R|R|R|    Length   |   MD Type   |  Next Proto   |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                Service Path ID                | Service Index |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                                                               |
+ * ~               Mandatory/Optional Context Header               ~
+ * |                                                               |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * Ver = The version field is used to ensure backward compatibility
+ *       going forward with future NSH updates.  It MUST be set to 0x0
+ *       by the sender, in this first revision of NSH.
+ *
+ * O = OAM. when set to 0x1 indicates that this packet is an operations
+ *     and management (OAM) packet.  The receiving SFF and SFs nodes
+ *     MUST examine the payload and take appropriate action.
+ *
+ * C = context. Indicates that a critical metadata TLV is present.
+ *
+ * Length : total length, in 4-byte words, of NSH including the Base
+ *          Header, the Service Path Header and the optional variable
+ *          TLVs.
+ * MD Type: indicates the format of NSH beyond the mandatory Base Header
+ *          and the Service Path Header.
+ *
+ * Next Protocol: indicates the protocol type of the original packet. A
+ *          new IANA registry will be created for protocol type.
+ *
+ * Service Path Identifier (SPI): identifies a service path.
+ *          Participating nodes MUST use this identifier for Service
+ *          Function Path selection.
+ *
+ * Service Index (SI): provides location within the SFP.
+ *
+ * [0] https://tools.ietf.org/html/draft-ietf-sfc-nsh-01
+ */
+struct nsh_base {
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+       __u8    reserved_flags1:4;
+       __u8    context_flag:1;
+       __u8    oam_flag:1;
+       __u8    version:2;
+
+       __u8    length:6;
+       __u8    reserved_flags2:2;
+#elif defined(__BIG_ENDIAN_BITFIELD)
+       __u8    version:2;
+       __u8    oam_flag:1;
+       __u8    context_flag:1;
+       __u8    reserved_flags1:4;
+
+       __u8    reserved_flags2:2;
+       __u8    length:6;
+#else
+#error "Bitfield Endianess not defined."
+#endif
+       __u8    md_type;
+       __u8    next_proto;
+       union {
+               struct {
+                       __u8    svc_path[3];
+                       __u8    svc_idx;
+               };
+               __be32 path_hdr;
+       };
+};
+
+/**
+ * struct nsh_md1_ctx - Keeps track of NSH context data
+ * @nshc<1-4>: NSH Contexts.
+ */
+struct nsh_md1_ctx {
+       __be32 nshc1;
+       __be32 nshc2;
+       __be32 nshc3;
+       __be32 nshc4;
+};
+
+struct nsh_md2_ctx {
+       __be16 md_class;
+       uint8_t type;
+       uint8_t length;
+       uint8_t md_value[];
+};
+
+/**
+ * struct nshdr - Network Service header
+ * @base: Network Service Base Header.
+ * @ctx: Network Service Context Header.
+ */
+struct nsh_hdr {
+       struct nsh_base base;
+       __be32 ctx[0]; /* Mandatory/optional Context Header */
+};
+
+#define NSH_DST_PORT    4790   /* UDP Port for NSH on VXLAN */
+#define ETH_P_NSH       0x894F   /* Ethertype for NSH */
+
+/* NSH Base Header Next Protocol */
+#define NSH_P_IPV4        0x01
+#define NSH_P_IPV6        0x02
+#define NSH_P_ETHERNET    0x03
+
+/* MD Type Registry */
+#define NSH_M_TYPE1     0x01
+#define NSH_M_TYPE2     0x02
+#define NSH_M_EXP1      0xFE
+#define NSH_M_EXP2      0xFF
+
+/* Used for masking nsp and nsi values in field nsp below */
+#define NSH_M_NSP   0x00FFFFFF
+#define NSH_M_NSI   0xFF000000
+
+/* sizeof(struct nsh_hdr) + sizeof(struct nsh_md1_ctx) */
+#define NSH_M_TYPE1_LEN     24
+#define NSH_LEN_MAX        256
+
+#endif
-- 
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.

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

Reply via email to