[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