Regards _Sugesh
> -----Original Message----- > From: dev [mailto:dev-boun...@openvswitch.org] On Behalf Of Johnson Li > Sent: Tuesday, June 7, 2016 7:10 PM > To: dev@openvswitch.org > Subject: [ovs-dev] [CudaMailTagged] [RFC PATCH 10/14] Parse NSH header in > flow_extract > Importance: Low > > Signed-off-by: Johnson Li <johnson...@intel.com> > > diff --git a/lib/flow.c b/lib/flow.c > index a4c1215..be87b3c 100644 > --- a/lib/flow.c > +++ b/lib/flow.c > @@ -439,6 +439,37 @@ invalid: > arp_buf[1] = eth_addr_zero; > } > > +static inline int > +parse_nsh(const void **datap, size_t *sizep, struct flow_nsh *key) { > + const struct nsh_header *nsh = (const struct nsh_header *) *datap; > + uint16_t length = 0; > + > + memset(key, 0, sizeof(struct flow_nsh)); > + > + /* MD Type 1 is supported only at the moment. */ > + if (nsh->base.md_type != NSH_MD_TYPE1) > + return -EINVAL; > + > + length = nsh->base.length << 2; > + if (length > NSH_LEN_MAX) > + return -EINVAL; [Sugesh] Is this validation make sure that he length shouldn’t be greater than 6*4 bytes ? Should we have to validating against maximum size than 6? > + > + 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; > + key->nshc1 = nsh->ctx.nshc1; > + key->nshc2 = nsh->ctx.nshc2; > + key->nshc3 = nsh->ctx.nshc3; > + key->nshc4 = nsh->ctx.nshc4; > + > + 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 > +594,16 @@ 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; > + [Sugesh] Rename this variable to make it more readable at 'miniflow_push_words' function call? There are two nsh that points to different terms > + if (OVS_LIKELY(!parse_nsh(&data, &size, &nsh))) > + miniflow_push_words(mf, nsh, &nsh, sizeof(struct flow_nsh) / > + sizeof(uint64_t)); > + goto out; > + } > + > nw_frag = 0; > if (OVS_LIKELY(dl_type == htons(ETH_TYPE_IP))) { > const struct ip_header *nh = data; @@ -1293,6 +1334,19 @@ void > flow_wildcards_init_for_packet(struct flow_wildcards *wc, > WC_MASK_FIELD(wc, dp_hash); > WC_MASK_FIELD(wc, in_port); > > + /* NSH fields wildcards, MD type 1 only */ > + if (flow->nsh.md_type) { > + 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 +1451,19 @@ flow_wc_map(const struct flow *flow, struct > flowmap *map) > FLOWMAP_SET(map, ct_mark); > FLOWMAP_SET(map, ct_label); > > + /* NSH fields */ > + if (flow->nsh.md_type) { > + 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..43ecfd8 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) { @@ -347,6 +348,11 > @@ static inline bool eth_type_vlan(ovs_be16 eth_type) > eth_type == htons(ETH_TYPE_VLAN_8021AD); } > > +static inline bool eth_type_nsh(ovs_be16 eth_type) { > + return eth_type == htons(ETH_TYPE_NSH); } > + > > /* Minimum value for an Ethernet type. Values below this are IEEE 802.2 > frame > * lengths. */ > @@ -1018,6 +1024,44 @@ struct vxlanhdr { > > #define VXLAN_FLAGS 0x08000000 /* struct vxlanhdr.vx_flags required > value. */ > > +/* Network service header */ > +struct nsh_base_hdr { [Sugesh] I don’t find the version field in the header? Any reason for not included in the header? Shouldn’t we need it for the future extensions? > + 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; > +}; > + > +/* MD Type 1 only, Todo: Type 2 support */ > +struct nsh_header { > + struct nsh_base_hdr base; [Sugesh] Can you name it as md1_ctx, So that when the MD2 support added as a union, its easy to identify between those. > + struct nsh_md1_ctx ctx; > +}; > + > +#define NSH_P_IPV4 0x01 > +#define NSH_P_IPV6 0x02 > +#define NSH_P_ETHERNET 0x03 > +#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 > > _______________________________________________ > dev mailing list > dev@openvswitch.org > http://openvswitch.org/mailman/listinfo/dev _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev