[ovs-dev] [CudaMailTagged] [RFC PATCH 06/14] Parse and format NSH key attributes
Johnson Li
johnson.li at intel.com
Tue Jun 7 18:09:48 UTC 2016
Signed-off-by: Johnson Li <johnson.li at intel.com>
diff --git a/lib/odp-util.c b/lib/odp-util.c
index d9ace90..8a2e521 100644
--- a/lib/odp-util.c
+++ b/lib/odp-util.c
@@ -146,6 +146,7 @@ ovs_key_attr_to_string(enum ovs_key_attr attr, char *namebuf, size_t bufsize)
case OVS_KEY_ATTR_CT_MARK: return "ct_mark";
case OVS_KEY_ATTR_CT_LABELS: return "ct_label";
case OVS_KEY_ATTR_TUNNEL: return "tunnel";
+ case OVS_KEY_ATTR_NSH: return "nsh";
case OVS_KEY_ATTR_IN_PORT: return "in_port";
case OVS_KEY_ATTR_ETHERNET: return "eth";
case OVS_KEY_ATTR_VLAN: return "vlan";
@@ -1748,6 +1749,18 @@ static const struct attr_len_tbl ovs_tun_key_attr_lens[OVS_TUNNEL_KEY_ATTR_MAX +
[OVS_TUNNEL_KEY_ATTR_IPV6_DST] = { .len = 16 },
};
+static const struct attr_len_tbl ovs_nsh_key_attr_lens[OVS_NSH_KEY_ATTR_MAX + 1] = {
+ [OVS_NSH_KEY_ATTR_FLAGS] = { .len = 1 },
+ [OVS_NSH_KEY_ATTR_MD_TYPE] = { .len = 1 },
+ [OVS_NSH_KEY_ATTR_NEXT_PROTO] = { .len = 1 },
+ [OVS_NSH_KEY_ATTR_NSI] = { .len = 1 },
+ [OVS_NSH_KEY_ATTR_NSP] = { .len = 4 },
+ [OVS_NSH_KEY_ATTR_NSHC1] = { .len = 4 },
+ [OVS_NSH_KEY_ATTR_NSHC2] = { .len = 4 },
+ [OVS_NSH_KEY_ATTR_NSHC3] = { .len = 4 },
+ [OVS_NSH_KEY_ATTR_NSHC4] = { .len = 4 },
+};
+
static const struct attr_len_tbl ovs_flow_key_attr_lens[OVS_KEY_ATTR_MAX + 1] = {
[OVS_KEY_ATTR_ENCAP] = { .len = ATTR_LEN_NESTED },
[OVS_KEY_ATTR_PRIORITY] = { .len = 4 },
@@ -1760,6 +1773,9 @@ static const struct attr_len_tbl ovs_flow_key_attr_lens[OVS_KEY_ATTR_MAX + 1] =
[OVS_KEY_ATTR_IN_PORT] = { .len = 4 },
[OVS_KEY_ATTR_ETHERNET] = { .len = sizeof(struct ovs_key_ethernet) },
[OVS_KEY_ATTR_VLAN] = { .len = 2 },
+ [OVS_KEY_ATTR_NSH] = { .len = ATTR_LEN_NESTED,
+ .next = ovs_nsh_key_attr_lens,
+ .next_max = OVS_NSH_KEY_ATTR_MAX },
[OVS_KEY_ATTR_ETHERTYPE] = { .len = 2 },
[OVS_KEY_ATTR_MPLS] = { .len = ATTR_LEN_VARIABLE },
[OVS_KEY_ATTR_IPV4] = { .len = sizeof(struct ovs_key_ipv4) },
@@ -1994,6 +2010,105 @@ tun_key_to_attr(struct ofpbuf *a, const struct flow_tnl *tun_key,
nl_msg_end_nested(a, tun_key_ofs);
}
+static void
+nsh_key_to_attr(struct ofpbuf *a, const struct flow_nsh *nsh_key)
+{
+ size_t nsh_key_ofs = 0;
+
+ if (nsh_key->md_type) {
+ nsh_key_ofs = nl_msg_start_nested(a, OVS_KEY_ATTR_NSH);
+
+ if (nsh_key->flags) {
+ nl_msg_put_u8(a, OVS_NSH_KEY_ATTR_FLAGS, nsh_key->flags);
+ }
+ if (nsh_key->md_type) {
+ nl_msg_put_u8(a, OVS_NSH_KEY_ATTR_MD_TYPE, nsh_key->md_type);
+ }
+ if (nsh_key->next_proto) {
+ nl_msg_put_u8(a, OVS_NSH_KEY_ATTR_NEXT_PROTO, nsh_key->next_proto);
+ }
+ if (nsh_key->nsi) {
+ nl_msg_put_u8(a, OVS_NSH_KEY_ATTR_NSI, nsh_key->nsi);
+ }
+ if (nsh_key->nsp) {
+ nl_msg_put_be32(a, OVS_NSH_KEY_ATTR_NSP, nsh_key->nsp);
+ }
+ if (nsh_key->nsp) {
+ nl_msg_put_be32(a, OVS_NSH_KEY_ATTR_NSHC1, nsh_key->nshc1);
+ }
+ if (nsh_key->nsp) {
+ nl_msg_put_be32(a, OVS_NSH_KEY_ATTR_NSHC2, nsh_key->nshc2);
+ }
+ if (nsh_key->nsp) {
+ nl_msg_put_be32(a, OVS_NSH_KEY_ATTR_NSHC3, nsh_key->nshc3);
+ }
+ if (nsh_key->nsp) {
+ nl_msg_put_be32(a, OVS_NSH_KEY_ATTR_NSHC4, nsh_key->nshc4);
+ }
+
+ nl_msg_end_nested(a, nsh_key_ofs);
+ }
+}
+
+static enum odp_key_fitness
+odp_nsh_key_from_attr__(const struct nlattr *attr, struct flow_nsh *nsh)
+{
+ unsigned int left;
+ const struct nlattr *a;
+ bool unknown = false;
+
+ NL_NESTED_FOR_EACH(a, left, attr) {
+ uint16_t type = nl_attr_type(a);
+ size_t len = nl_attr_get_size(a);
+ int expected_len = odp_key_attr_len(ovs_nsh_key_attr_lens,
+ OVS_NSH_KEY_ATTR_MAX, type);
+
+ if (len != expected_len && expected_len >= 0) {
+ return ODP_FIT_ERROR;
+ }
+
+ switch (type) {
+ case OVS_NSH_KEY_ATTR_FLAGS:
+ nsh->flags = nl_attr_get_u8(a);
+ break;
+ case OVS_NSH_KEY_ATTR_MD_TYPE:
+ nsh->md_type = nl_attr_get_u8(a);
+ break;
+ case OVS_NSH_KEY_ATTR_NEXT_PROTO:
+ nsh->next_proto = nl_attr_get_u8(a);
+ break;
+ case OVS_NSH_KEY_ATTR_NSI:
+ nsh->nsi = nl_attr_get_u8(a);
+ break;
+ case OVS_NSH_KEY_ATTR_NSP:
+ nsh->nsp = nl_attr_get_be32(a);
+ break;
+ case OVS_NSH_KEY_ATTR_NSHC1:
+ nsh->nshc1 = nl_attr_get_be32(a);
+ break;
+ case OVS_NSH_KEY_ATTR_NSHC2:
+ nsh->nshc2 = nl_attr_get_be32(a);
+ break;
+ case OVS_NSH_KEY_ATTR_NSHC3:
+ nsh->nshc3 = nl_attr_get_be32(a);
+ break;
+ case OVS_NSH_KEY_ATTR_NSHC4:
+ nsh->nshc4 = nl_attr_get_be32(a);
+ break;
+ default:
+ /* Allow this to show up as unexpected, if there are unknown
+ * NSH attribute, eventually resulting in ODP_FIT_TOO_MUCH. */
+ unknown = true;
+ break;
+ }
+ }
+
+ if (unknown) {
+ return ODP_FIT_TOO_MUCH;
+ }
+ return ODP_FIT_PERFECT;
+}
+
static bool
odp_mask_attr_is_wildcard(const struct nlattr *ma)
{
@@ -2019,7 +2134,8 @@ odp_mask_is_exact(enum ovs_key_attr attr, const void *mask, size_t size)
&& ipv6_mask_is_exact((const struct in6_addr *)ipv6_mask->ipv6_src)
&& ipv6_mask_is_exact((const struct in6_addr *)ipv6_mask->ipv6_dst);
}
- if (attr == OVS_KEY_ATTR_TUNNEL) {
+ if (attr == OVS_KEY_ATTR_TUNNEL ||
+ attr == OVS_KEY_ATTR_NSH) {
return false;
}
@@ -2041,7 +2157,8 @@ odp_mask_attr_is_exact(const struct nlattr *ma)
const void *mask;
size_t size;
- if (attr == OVS_KEY_ATTR_TUNNEL) {
+ if (attr == OVS_KEY_ATTR_TUNNEL ||
+ attr == OVS_KEY_ATTR_NSH) {
return false;
} else {
mask = nl_attr_get(ma);
@@ -2128,6 +2245,23 @@ format_be64(struct ds *ds, const char *name, ovs_be64 key,
}
static void
+format_be32(struct ds *ds, const char *name, ovs_be32 key,
+ const ovs_be32 *mask, bool verbose)
+{
+ bool mask_empty = mask && !*mask;
+
+ if (verbose || !mask_empty) {
+ bool mask_full = !mask || *mask == OVS_BE32_MAX;
+
+ ds_put_format(ds, "%s=0x%"PRIx32, name, ntohl(key));
+ if (!mask_full) { /* Partially masked. */
+ ds_put_format(ds, "/%#"PRIx32, ntohl(*mask));
+ }
+ ds_put_char(ds, ',');
+ }
+}
+
+static void
format_ipv4(struct ds *ds, const char *name, ovs_be32 key,
const ovs_be32 *mask, bool verbose)
{
@@ -2596,6 +2730,82 @@ format_odp_tun_attr(const struct nlattr *attr, const struct nlattr *mask_attr,
ofpbuf_uninit(&ofp);
}
+static void
+format_odp_nsh_attr(const struct nlattr *attr, const struct nlattr *mask_attr,
+ struct ds *ds, bool verbose)
+{
+ unsigned int left;
+ const struct nlattr *a;
+ struct ofpbuf ofp;
+
+ ofpbuf_init(&ofp, 100);
+ NL_NESTED_FOR_EACH(a, left, attr) {
+ enum ovs_nsh_key_attr type = nl_attr_type(a);
+ const struct nlattr *ma = NULL;
+
+ if (mask_attr) {
+ ma = nl_attr_find__(nl_attr_get(mask_attr),
+ nl_attr_get_size(mask_attr), type);
+ if (!ma) {
+ ma = generate_all_wildcard_mask(ovs_nsh_key_attr_lens,
+ OVS_NSH_KEY_ATTR_MAX,
+ &ofp, a);
+ }
+ }
+
+ if (!check_attr_len(ds, a, ma, ovs_nsh_key_attr_lens,
+ OVS_NSH_KEY_ATTR_MAX, true)) {
+ continue;
+ }
+
+ switch (type) {
+ case OVS_NSH_KEY_ATTR_FLAGS:
+ format_u8x(ds, "flags", nl_attr_get_u8(a),
+ ma ? nl_attr_get(ma) : NULL, verbose);
+ break;
+ case OVS_NSH_KEY_ATTR_MD_TYPE:
+ format_u8u(ds, "nsh_mdtype", nl_attr_get_u8(a),
+ ma ? nl_attr_get(ma) : NULL, verbose);
+ break;
+ case OVS_NSH_KEY_ATTR_NEXT_PROTO:
+ format_u8u(ds, "nsh_np", nl_attr_get_u8(a),
+ ma ? nl_attr_get(ma) : NULL, verbose);
+ break;
+ case OVS_NSH_KEY_ATTR_NSI:
+ format_u8x(ds, "nsi", nl_attr_get_u8(a),
+ ma ? nl_attr_get(ma) : NULL, verbose);
+ break;
+ case OVS_NSH_KEY_ATTR_NSP:
+ format_be32(ds, "nsp", nl_attr_get_be32(a),
+ ma ? nl_attr_get(ma) : NULL, verbose);
+ break;
+ case OVS_NSH_KEY_ATTR_NSHC1:
+ format_be32(ds, "nshc1", nl_attr_get_be32(a),
+ ma ? nl_attr_get(ma) : NULL, verbose);
+ break;
+ case OVS_NSH_KEY_ATTR_NSHC2:
+ format_be32(ds, "nshc2", nl_attr_get_be32(a),
+ ma ? nl_attr_get(ma) : NULL, verbose);
+ break;
+ case OVS_NSH_KEY_ATTR_NSHC3:
+ format_be32(ds, "nshc3", nl_attr_get_be32(a),
+ ma ? nl_attr_get(ma) : NULL, verbose);
+ break;
+ case OVS_NSH_KEY_ATTR_NSHC4:
+ format_be32(ds, "nshc4", nl_attr_get_be32(a),
+ ma ? nl_attr_get(ma) : NULL, verbose);
+ break;
+ case __OVS_NSH_KEY_ATTR_MAX:
+ default:
+ format_unknown_key(ds, a, ma);
+ }
+ ofpbuf_clear(&ofp);
+ }
+
+ ds_chomp(ds, ',');
+ ofpbuf_uninit(&ofp);
+}
+
static const char *
odp_ct_state_to_string(uint32_t flag)
{
@@ -2743,6 +2953,10 @@ format_odp_key_attr(const struct nlattr *a, const struct nlattr *ma,
format_odp_tun_attr(a, ma, ds, verbose);
break;
+ case OVS_KEY_ATTR_NSH:
+ format_odp_nsh_attr(a, ma, ds, verbose);
+ break;
+
case OVS_KEY_ATTR_IN_PORT:
if (portno_names && verbose && is_exact) {
char *name = odp_portno_names_get(portno_names,
@@ -4035,6 +4249,18 @@ parse_odp_key_mask_attr(const char *s, const struct simap *port_names,
SCAN_FIELD_NESTED_FUNC("flags(", uint16_t, tun_flags, tun_flags_to_attr);
} SCAN_END_NESTED();
+ SCAN_BEGIN_NESTED("nsh(", OVS_KEY_ATTR_NSH) {
+ SCAN_FIELD_NESTED("flags=", uint8_t, u8, OVS_NSH_KEY_ATTR_FLAGS);
+ SCAN_FIELD_NESTED("nsh_mdtype=", uint8_t, u8, OVS_NSH_KEY_ATTR_MD_TYPE);
+ SCAN_FIELD_NESTED("nsh_np=", uint8_t, u8, OVS_NSH_KEY_ATTR_NEXT_PROTO);
+ SCAN_FIELD_NESTED("nsi=", uint8_t, u8, OVS_NSH_KEY_ATTR_NSI);
+ SCAN_FIELD_NESTED("nsp=", uint32_t, u32, OVS_NSH_KEY_ATTR_NSP);
+ SCAN_FIELD_NESTED("nshc1=", uint32_t, u32, OVS_NSH_KEY_ATTR_NSHC1);
+ SCAN_FIELD_NESTED("nshc2=", uint32_t, u32, OVS_NSH_KEY_ATTR_NSHC2);
+ SCAN_FIELD_NESTED("nshc3=", uint32_t, u32, OVS_NSH_KEY_ATTR_NSHC3);
+ SCAN_FIELD_NESTED("nshc4=", uint32_t, u32, OVS_NSH_KEY_ATTR_NSHC4);
+ } SCAN_END_NESTED();
+
SCAN_SINGLE_PORT("in_port(", uint32_t, OVS_KEY_ATTR_IN_PORT);
SCAN_BEGIN("eth(", struct ovs_key_ethernet) {
@@ -4253,6 +4479,10 @@ odp_flow_key_from_flow__(const struct odp_flow_key_parms *parms,
parms->key_buf);
}
+ if (flow->nsh.md_type) {
+ nsh_key_to_attr(buf, &data->nsh);
+ }
+
nl_msg_put_u32(buf, OVS_KEY_ATTR_SKB_MARK, data->pkt_mark);
if (parms->support.ct_state) {
@@ -5129,6 +5359,18 @@ odp_flow_key_to_flow__(const struct nlattr *key, size_t key_len,
}
}
+ /* Network Service Header. */
+ if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_NSH)) {
+ enum odp_key_fitness res;
+
+ res = odp_nsh_key_from_attr__(attrs[OVS_KEY_ATTR_NSH], &flow->nsh);
+ if (res == ODP_FIT_ERROR) {
+ return ODP_FIT_ERROR;
+ } else if (res == ODP_FIT_PERFECT) {
+ expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_NSH;
+ }
+ }
+
if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_IN_PORT)) {
flow->in_port.odp_port
= nl_attr_get_odp_port(attrs[OVS_KEY_ATTR_IN_PORT]);
--
1.8.4.2
More information about the dev
mailing list