Skip to content

Commit

Permalink
nsh: rework NSH netlink keys and actions
Browse files Browse the repository at this point in the history
This patch changes OVS_KEY_ATTR_NSH
to nested attribute and adds three new NSH sub attribute keys:

    OVS_NSH_KEY_ATTR_BASE: for length-fixed NSH base header
    OVS_NSH_KEY_ATTR_MD1:  for length-fixed MD type 1 context
    OVS_NSH_KEY_ATTR_MD2:  for length-variable MD type 2 metadata

Its intention is to align to NSH kernel implementation.

NSH match fields, set and PUSH_NSH action all use the below
nested attribute format:

OVS_KEY_ATTR_NSH begin
    OVS_NSH_KEY_ATTR_BASE
    OVS_NSH_KEY_ATTR_MD1
OVS_KEY_ATTR_NSH end

or

OVS_KEY_ATTR_NSH begin
    OVS_NSH_KEY_ATTR_BASE
    OVS_NSH_KEY_ATTR_MD2
OVS_KEY_ATTR_NSH end

In addition, NSH encap and decap actions are renamed as push_nsh
and pop_nsh to meet action naming convention.

Signed-off-by: Yi Yang <[email protected]>
Signed-off-by: Ben Pfaff <[email protected]>
  • Loading branch information
yi-y-yang authored and blp committed Jan 8, 2018
1 parent d3b8483 commit f59cb33
Show file tree
Hide file tree
Showing 18 changed files with 786 additions and 286 deletions.
58 changes: 27 additions & 31 deletions datapath/linux/compat/include/linux/openvswitch.h
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ enum ovs_key_attr {
#ifndef __KERNEL__
/* Only used within userspace data path. */
OVS_KEY_ATTR_PACKET_TYPE, /* be32 packet type */
OVS_KEY_ATTR_NSH, /* struct ovs_key_nsh */
OVS_KEY_ATTR_NSH, /* Nested set of ovs_nsh_key_* */
#endif

__OVS_KEY_ATTR_MAX
Expand Down Expand Up @@ -492,13 +492,28 @@ struct ovs_key_ct_labels {
};
};

struct ovs_key_nsh {
__u8 flags;
__u8 mdtype;
__u8 np;
__u8 pad;
__be32 path_hdr;
__be32 c[4];
enum ovs_nsh_key_attr {
OVS_NSH_KEY_ATTR_UNSPEC,
OVS_NSH_KEY_ATTR_BASE, /* struct ovs_nsh_key_base. */
OVS_NSH_KEY_ATTR_MD1, /* struct ovs_nsh_key_md1. */
OVS_NSH_KEY_ATTR_MD2, /* variable-length octets. */
__OVS_NSH_KEY_ATTR_MAX
};

#define OVS_NSH_KEY_ATTR_MAX (__OVS_NSH_KEY_ATTR_MAX - 1)

struct ovs_nsh_key_base {
__u8 flags;
__u8 mdtype;
__u8 np;
__u8 pad;
__be32 path_hdr;
};

#define NSH_MD1_CONTEXT_SIZE 4

struct ovs_nsh_key_md1 {
__be32 context[NSH_MD1_CONTEXT_SIZE];
};

/* OVS_KEY_ATTR_CT_STATE flags */
Expand Down Expand Up @@ -793,25 +808,6 @@ struct ovs_action_push_eth {
struct ovs_key_ethernet addresses;
};

#define OVS_ENCAP_NSH_MAX_MD_LEN 248
/*
* struct ovs_action_encap_nsh - %OVS_ACTION_ATTR_ENCAP_NSH
* @flags: NSH header flags.
* @mdtype: NSH metadata type.
* @mdlen: Length of NSH metadata in bytes, including padding.
* @np: NSH next_protocol: Inner packet type.
* @path_hdr: NSH service path id and service index.
* @metadata: NSH context metadata, padded to 4-bytes
*/
struct ovs_action_encap_nsh {
uint8_t flags;
uint8_t mdtype;
uint8_t mdlen;
uint8_t np;
__be32 path_hdr;
uint8_t metadata[OVS_ENCAP_NSH_MAX_MD_LEN];
};

/**
* enum ovs_nat_attr - Attributes for %OVS_CT_ATTR_NAT.
*
Expand Down Expand Up @@ -887,8 +883,8 @@ enum ovs_nat_attr {
* @OVS_ACTION_ATTR_PUSH_ETH: Push a new outermost Ethernet header onto the
* packet.
* @OVS_ACTION_ATTR_POP_ETH: Pop the outermost Ethernet header off the packet.
* @OVS_ACTION_ATTR_ENCAP_NSH: encap NSH action to push NSH header.
* @OVS_ACTION_ATTR_DECAP_NSH: decap NSH action to remove NSH header.
* @OVS_ACTION_ATTR_PUSH_NSH: push NSH header to the packet.
* @OVS_ACTION_ATTR_POP_NSH: pop the outermost NSH header off the packet.
*
* Only a single header can be set with a single %OVS_ACTION_ATTR_SET. Not all
* fields within a header are modifiable, e.g. the IPv4 protocol and fragment
Expand Down Expand Up @@ -930,8 +926,8 @@ enum ovs_action_attr {
OVS_ACTION_ATTR_TUNNEL_POP, /* u32 port number. */
OVS_ACTION_ATTR_CLONE, /* Nested OVS_CLONE_ATTR_*. */
OVS_ACTION_ATTR_METER, /* u32 meter number. */
OVS_ACTION_ATTR_ENCAP_NSH, /* struct ovs_action_encap_nsh. */
OVS_ACTION_ATTR_DECAP_NSH, /* No argument. */
OVS_ACTION_ATTR_PUSH_NSH, /* Nested OVS_NSH_KEY_ATTR_*. */
OVS_ACTION_ATTR_POP_NSH, /* No argument. */
#endif
__OVS_ACTION_ATTR_MAX, /* Nothing past this will be accepted
* from userspace. */
Expand Down
26 changes: 19 additions & 7 deletions include/openvswitch/nsh.h
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ extern "C" {
* @nshc<1-4>: NSH Contexts.
*/
struct nsh_md1_ctx {
ovs_16aligned_be32 c[4];
ovs_16aligned_be32 context[4];
};

struct nsh_md2_tlv {
Expand Down Expand Up @@ -262,6 +262,12 @@ struct nsh_hdr {
/* NSH MD Type 1 header Length. */
#define NSH_M_TYPE1_LEN 24

/* NSH header maximum Length. */
#define NSH_HDR_MAX_LEN 256

/* NSH context headers maximum Length. */
#define NSH_CTX_HDRS_MAX_LEN 248

static inline uint16_t
nsh_hdr_len(const struct nsh_hdr *nsh)
{
Expand All @@ -275,16 +281,22 @@ nsh_md_type(const struct nsh_hdr *nsh)
return (nsh->md_type & NSH_MDTYPE_MASK) >> NSH_MDTYPE_SHIFT;
}

static inline struct nsh_md1_ctx *
nsh_md1_ctx(struct nsh_hdr *nsh)
static inline uint8_t
nsh_get_ver(const struct nsh_hdr *nsh)
{
return (ntohs(nsh->ver_flags_ttl_len) & NSH_VER_MASK) >> NSH_VER_SHIFT;
}

static inline uint8_t
nsh_get_flags(const struct nsh_hdr *nsh)
{
return &nsh->md1;
return (ntohs(nsh->ver_flags_ttl_len) & NSH_FLAGS_MASK) >> NSH_FLAGS_SHIFT;
}

static inline struct nsh_md2_tlv *
nsh_md2_ctx(struct nsh_hdr *nsh)
static inline void
nsh_reset_ver_flags_ttl_len(struct nsh_hdr *nsh)
{
return &nsh->md2;
nsh->ver_flags_ttl_len = 0;
}

#ifdef __cplusplus
Expand Down
11 changes: 10 additions & 1 deletion include/openvswitch/packets.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,16 @@ struct flow_nsh {
uint8_t np;
uint8_t si;
ovs_be32 spi;
ovs_be32 c[4];
ovs_be32 context[4];
};

struct ovs_key_nsh {
uint8_t flags;
uint8_t mdtype;
uint8_t np;
uint8_t pad;
ovs_be32 path_hdr;
ovs_be32 context[4];
};

/* NSH flags */
Expand Down
4 changes: 2 additions & 2 deletions lib/dpif-netdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -5760,8 +5760,8 @@ dp_execute_cb(void *aux_, struct dp_packet_batch *packets_,
case OVS_ACTION_ATTR_PUSH_ETH:
case OVS_ACTION_ATTR_POP_ETH:
case OVS_ACTION_ATTR_CLONE:
case OVS_ACTION_ATTR_ENCAP_NSH:
case OVS_ACTION_ATTR_DECAP_NSH:
case OVS_ACTION_ATTR_PUSH_NSH:
case OVS_ACTION_ATTR_POP_NSH:
case __OVS_ACTION_ATTR_MAX:
OVS_NOT_REACHED();
}
Expand Down
4 changes: 2 additions & 2 deletions lib/dpif.c
Original file line number Diff line number Diff line change
Expand Up @@ -1273,8 +1273,8 @@ dpif_execute_helper_cb(void *aux_, struct dp_packet_batch *packets_,
case OVS_ACTION_ATTR_PUSH_ETH:
case OVS_ACTION_ATTR_POP_ETH:
case OVS_ACTION_ATTR_CLONE:
case OVS_ACTION_ATTR_ENCAP_NSH:
case OVS_ACTION_ATTR_DECAP_NSH:
case OVS_ACTION_ATTR_PUSH_NSH:
case OVS_ACTION_ATTR_POP_NSH:
case OVS_ACTION_ATTR_UNSPEC:
case __OVS_ACTION_ATTR_MAX:
OVS_NOT_REACHED();
Expand Down
40 changes: 17 additions & 23 deletions lib/flow.c
Original file line number Diff line number Diff line change
Expand Up @@ -533,7 +533,6 @@ bool
parse_nsh(const void **datap, size_t *sizep, struct flow_nsh *key)
{
const struct nsh_hdr *nsh = (const struct nsh_hdr *) *datap;
uint16_t ver_flags_len;
uint8_t version, length, flags;
uint32_t path_hdr;

Expand All @@ -544,16 +543,11 @@ parse_nsh(const void **datap, size_t *sizep, struct flow_nsh *key)
return false;
}

memset(key, 0, sizeof(struct flow_nsh));
version = nsh_get_ver(nsh);
flags = nsh_get_flags(nsh);
length = nsh_hdr_len(nsh);

ver_flags_len = ntohs(nsh->ver_flags_ttl_len);
version = (ver_flags_len & NSH_VER_MASK) >> NSH_VER_SHIFT;
flags = (ver_flags_len & NSH_FLAGS_MASK) >> NSH_FLAGS_SHIFT;

/* NSH header length is in 4 byte words. */
length = ((ver_flags_len & NSH_LEN_MASK) >> NSH_LEN_SHIFT) << 2;

if (length > *sizep || version != 0) {
if (OVS_UNLIKELY(length > *sizep || version != 0)) {
return false;
}

Expand All @@ -571,10 +565,17 @@ parse_nsh(const void **datap, size_t *sizep, struct flow_nsh *key)
return false;
}
for (size_t i = 0; i < 4; i++) {
key->c[i] = get_16aligned_be32(&nsh->md1.c[i]);
key->context[i] = get_16aligned_be32(&nsh->md1.context[i]);
}
break;
case NSH_M_TYPE2:
/* Don't support MD type 2 metedata parsing yet */
if (length < NSH_BASE_HDR_LEN) {
return false;
}

memset(key->context, 0, sizeof(key->context));
break;
default:
/* We don't parse other context headers yet. */
break;
Expand Down Expand Up @@ -878,16 +879,9 @@ miniflow_extract(struct dp_packet *packet, struct miniflow *dst)
struct flow_nsh nsh;

if (OVS_LIKELY(parse_nsh(&data, &size, &nsh))) {
if (nsh.mdtype == NSH_M_TYPE1) {
miniflow_push_words(mf, nsh, &nsh,
sizeof(struct flow_nsh) /
sizeof(uint64_t));
}
else if (nsh.mdtype == NSH_M_TYPE2) {
/* parse_nsh has stopped it from arriving here for
* MD type 2, will add MD type 2 support code here later
*/
}
miniflow_push_words(mf, nsh, &nsh,
sizeof(struct flow_nsh) /
sizeof(uint64_t));
}
}
goto out;
Expand Down Expand Up @@ -1694,7 +1688,7 @@ flow_wildcards_init_for_packet(struct flow_wildcards *wc,
WC_MASK_FIELD(wc, nsh.np);
WC_MASK_FIELD(wc, nsh.spi);
WC_MASK_FIELD(wc, nsh.si);
WC_MASK_FIELD(wc, nsh.c);
WC_MASK_FIELD(wc, nsh.context);
} else {
return; /* Unknown ethertype. */
}
Expand Down Expand Up @@ -1828,7 +1822,7 @@ flow_wc_map(const struct flow *flow, struct flowmap *map)
FLOWMAP_SET(map, nsh.np);
FLOWMAP_SET(map, nsh.spi);
FLOWMAP_SET(map, nsh.si);
FLOWMAP_SET(map, nsh.c);
FLOWMAP_SET(map, nsh.context);
}
}

Expand Down
12 changes: 8 additions & 4 deletions lib/match.c
Original file line number Diff line number Diff line change
Expand Up @@ -1266,10 +1266,14 @@ format_nsh_masked(struct ds *s, const struct flow *f, const struct flow *m)
format_be32_masked_hex(s, "nsh_spi", f->nsh.spi, m->nsh.spi);
format_uint8_masked(s, "nsh_si", f->nsh.si, m->nsh.si);
if (m->nsh.mdtype == UINT8_MAX && f->nsh.mdtype == NSH_M_TYPE1) {
format_be32_masked_hex(s, "nsh_c1", f->nsh.c[0], m->nsh.c[0]);
format_be32_masked_hex(s, "nsh_c2", f->nsh.c[1], m->nsh.c[1]);
format_be32_masked_hex(s, "nsh_c3", f->nsh.c[2], m->nsh.c[2]);
format_be32_masked_hex(s, "nsh_c4", f->nsh.c[3], m->nsh.c[3]);
format_be32_masked_hex(s, "nsh_c1", f->nsh.context[0],
m->nsh.context[0]);
format_be32_masked_hex(s, "nsh_c2", f->nsh.context[1],
m->nsh.context[1]);
format_be32_masked_hex(s, "nsh_c3", f->nsh.context[2],
m->nsh.context[2]);
format_be32_masked_hex(s, "nsh_c4", f->nsh.context[3],
m->nsh.context[3]);
}
}

Expand Down
13 changes: 7 additions & 6 deletions lib/meta-flow.c
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,7 @@ mf_is_all_wild(const struct mf_field *mf, const struct flow_wildcards *wc)
case MFF_NSH_C2:
case MFF_NSH_C3:
case MFF_NSH_C4:
return !wc->masks.nsh.c[mf->id - MFF_NSH_C1];
return !wc->masks.nsh.context[mf->id - MFF_NSH_C1];

case MFF_N_IDS:
default:
Expand Down Expand Up @@ -915,7 +915,7 @@ mf_get_value(const struct mf_field *mf, const struct flow *flow,
case MFF_NSH_C2:
case MFF_NSH_C3:
case MFF_NSH_C4:
value->be32 = flow->nsh.c[mf->id - MFF_NSH_C1];
value->be32 = flow->nsh.context[mf->id - MFF_NSH_C1];
break;

case MFF_N_IDS:
Expand Down Expand Up @@ -1230,7 +1230,8 @@ mf_set_value(const struct mf_field *mf,
case MFF_NSH_C2:
case MFF_NSH_C3:
case MFF_NSH_C4:
MATCH_SET_FIELD_BE32(match, nsh.c[mf->id - MFF_NSH_C1], value->be32);
MATCH_SET_FIELD_BE32(match, nsh.context[mf->id - MFF_NSH_C1],
value->be32);
break;

case MFF_N_IDS:
Expand Down Expand Up @@ -1621,7 +1622,7 @@ mf_set_flow_value(const struct mf_field *mf,
case MFF_NSH_C2:
case MFF_NSH_C3:
case MFF_NSH_C4:
flow->nsh.c[mf->id - MFF_NSH_C1] = value->be32;
flow->nsh.context[mf->id - MFF_NSH_C1] = value->be32;
break;

case MFF_N_IDS:
Expand Down Expand Up @@ -2112,7 +2113,7 @@ mf_set_wild(const struct mf_field *mf, struct match *match, char **err_str)
case MFF_NSH_C2:
case MFF_NSH_C3:
case MFF_NSH_C4:
MATCH_SET_FIELD_MASKED(match, nsh.c[mf->id - MFF_NSH_C1],
MATCH_SET_FIELD_MASKED(match, nsh.context[mf->id - MFF_NSH_C1],
htonl(0), htonl(0));
break;

Expand Down Expand Up @@ -2372,7 +2373,7 @@ mf_set(const struct mf_field *mf,
case MFF_NSH_C2:
case MFF_NSH_C3:
case MFF_NSH_C4:
MATCH_SET_FIELD_MASKED(match, nsh.c[mf->id - MFF_NSH_C1],
MATCH_SET_FIELD_MASKED(match, nsh.context[mf->id - MFF_NSH_C1],
value->be32, mask->be32);
break;

Expand Down
4 changes: 2 additions & 2 deletions lib/nx-match.c
Original file line number Diff line number Diff line change
Expand Up @@ -1165,8 +1165,8 @@ nx_put_raw(struct ofpbuf *b, enum ofp_version oxm, const struct match *match,
match->wc.masks.nsh.spi);
nxm_put_8m(&ctx, MFF_NSH_SI, oxm, flow->nsh.si, match->wc.masks.nsh.si);
for (int i = 0; i < 4; i++) {
nxm_put_32m(&ctx, MFF_NSH_C1 + i, oxm, flow->nsh.c[i],
match->wc.masks.nsh.c[i]);
nxm_put_32m(&ctx, MFF_NSH_C1 + i, oxm, flow->nsh.context[i],
match->wc.masks.nsh.context[i]);
}

/* Registers. */
Expand Down
Loading

0 comments on commit f59cb33

Please sign in to comment.