2
0
mirror of https://github.com/openvswitch/ovs synced 2025-08-31 06:15:47 +00:00

User-Space MPLS actions and matches

This patch implements use-space datapath and non-datapath code
to match and use the datapath API set out in Leo Alterman's patch
"user-space datapath: Add basic MPLS support to kernel".

The resulting MPLS implementation supports:
* Pushing a single MPLS label
* Poping a single MPLS label
* Modifying an MPLS lable using set-field or load actions
  that act on the label value, tc and bos bit.
* There is no support for manipulating the TTL
  this is considered future work.

The single-level push pop limitation is implemented by processing
push, pop and set-field/load actions in order and discarding information
that would require multiple levels of push/pop to be supported.

e.g.
   push,push -> the first push is discarded
   pop,pop -> the first pop is discarded

This patch is based heavily on work by Ravi K.

Cc: Ravi K <rkerur@gmail.com>
Reviewed-by: Isaku Yamahata <yamahata@valinux.co.jp>
Signed-off-by: Simon Horman <horms@verge.net.au>
Signed-off-by: Ben Pfaff <blp@nicira.com>
This commit is contained in:
Simon Horman
2013-01-25 16:22:07 +09:00
committed by Ben Pfaff
parent d224e35014
commit b02475c53b
29 changed files with 1223 additions and 61 deletions

View File

@@ -85,7 +85,7 @@ ofputil_netmask_to_wcbits(ovs_be32 netmask)
void
ofputil_wildcard_from_ofpfw10(uint32_t ofpfw, struct flow_wildcards *wc)
{
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 18);
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 19);
/* Initialize most of wc. */
flow_wildcards_init_catchall(wc);
@@ -440,8 +440,7 @@ ofputil_match_from_ofp11_match(const struct ofp11_match *ofmatch,
}
}
if (match->flow.dl_type == htons(ETH_TYPE_MPLS) ||
match->flow.dl_type == htons(ETH_TYPE_MPLS_MCAST)) {
if (eth_type_mpls(match->flow.dl_type)) {
enum { OFPFW11_MPLS_ALL = OFPFW11_MPLS_LABEL | OFPFW11_MPLS_TC };
if ((wc & OFPFW11_MPLS_ALL) != OFPFW11_MPLS_ALL) {
@@ -1060,7 +1059,7 @@ ofputil_usable_protocols(const struct match *match)
{
const struct flow_wildcards *wc = &match->wc;
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 18);
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 19);
/* tunnel params other than tun_id can't be sent in a flow_mod */
if (!tun_parms_fully_wildcarded(wc)) {
@@ -1152,6 +1151,26 @@ ofputil_usable_protocols(const struct match *match)
| OFPUTIL_P_OF13_OXM;
}
/* NXM and OF1.1+ support matching MPLS label */
if (wc->masks.mpls_lse & htonl(MPLS_LABEL_MASK)) {
return OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM
| OFPUTIL_P_OF13_OXM;
}
/* NXM and OF1.1+ support matching MPLS TC */
if (wc->masks.mpls_lse & htonl(MPLS_TC_MASK)) {
return OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM
| OFPUTIL_P_OF13_OXM;
}
/* NXM and OF1.3+ support matching MPLS stack flag */
/* Allow for OF1.2 as there doesn't seem to be a
* particularly good reason not to */
if (wc->masks.mpls_lse & htonl(MPLS_BOS_MASK)) {
return OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM
| OFPUTIL_P_OF13_OXM;
}
/* Other formats can express this rule. */
return OFPUTIL_P_ANY;
}
@@ -4307,7 +4326,8 @@ ofputil_normalize_match__(struct match *match, bool may_log)
MAY_ARP_SHA = 1 << 4, /* arp_sha */
MAY_ARP_THA = 1 << 5, /* arp_tha */
MAY_IPV6 = 1 << 6, /* ipv6_src, ipv6_dst, ipv6_label */
MAY_ND_TARGET = 1 << 7 /* nd_target */
MAY_ND_TARGET = 1 << 7, /* nd_target */
MAY_MPLS = 1 << 8, /* mpls label and tc */
} may_match;
struct flow_wildcards wc;
@@ -4336,6 +4356,8 @@ ofputil_normalize_match__(struct match *match, bool may_log)
} else if (match->flow.dl_type == htons(ETH_TYPE_ARP) ||
match->flow.dl_type == htons(ETH_TYPE_RARP)) {
may_match = MAY_NW_PROTO | MAY_NW_ADDR | MAY_ARP_SHA | MAY_ARP_THA;
} else if (eth_type_mpls(match->flow.dl_type)) {
may_match = MAY_MPLS;
} else {
may_match = 0;
}
@@ -4368,6 +4390,10 @@ ofputil_normalize_match__(struct match *match, bool may_log)
if (!(may_match & MAY_ND_TARGET)) {
wc.masks.nd_target = in6addr_any;
}
if (!(may_match & MAY_MPLS)) {
wc.masks.mpls_lse = htonl(0);
wc.masks.mpls_depth = 0;
}
/* Log any changes. */
if (!flow_wildcards_equal(&wc, &match->wc)) {