[ovs-dev] [CudaMailTagged] [RFC PATCH 10/14] Parse NSH header in flow_extract

Chandran, Sugesh sugesh.chandran at intel.com
Thu Jun 16 12:58:38 UTC 2016



Regards
_Sugesh


> -----Original Message-----
> From: dev [mailto:dev-bounces at openvswitch.org] On Behalf Of Johnson Li
> Sent: Tuesday, June 7, 2016 7:10 PM
> To: dev at openvswitch.org
> Subject: [ovs-dev] [CudaMailTagged] [RFC PATCH 10/14] Parse NSH header in
> flow_extract
> Importance: Low
> 
> Signed-off-by: Johnson Li <johnson.li at 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 at openvswitch.org
> http://openvswitch.org/mailman/listinfo/dev


More information about the dev mailing list