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; + + 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; + + 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 { + 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; + 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