Skip to content

Commit

Permalink
Add OF11 SET MPLS LABEL and SET MPLS TC actions.
Browse files Browse the repository at this point in the history
Signed-off-by: Jarno Rajahalme <[email protected]>
Signed-off-by: Ben Pfaff <[email protected]>
Reviewed-by: Simon Horman <[email protected]>
  • Loading branch information
Jarno Rajahalme authored and blp committed Nov 2, 2013
1 parent 6cc17de commit 097d493
Show file tree
Hide file tree
Showing 8 changed files with 261 additions and 15 deletions.
24 changes: 24 additions & 0 deletions include/openflow/nicira-ext.h
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,8 @@ enum nx_action_subtype {
NXAST_STACK_PUSH, /* struct nx_action_stack */
NXAST_STACK_POP, /* struct nx_action_stack */
NXAST_SAMPLE, /* struct nx_action_sample */
NXAST_SET_MPLS_LABEL, /* struct nx_action_ttl */
NXAST_SET_MPLS_TC, /* struct nx_action_ttl */
};

/* Header for Nicira-defined actions. */
Expand Down Expand Up @@ -2273,6 +2275,28 @@ struct nx_action_pop_mpls {
};
OFP_ASSERT(sizeof(struct nx_action_pop_mpls) == 16);

/* Action structure for NXAST_SET_MPLS_LABEL. */
struct nx_action_mpls_label {
ovs_be16 type; /* OFPAT_VENDOR. */
ovs_be16 len; /* Length is 8. */
ovs_be32 vendor; /* NX_VENDOR_ID. */
ovs_be16 subtype; /* NXAST_SET_MPLS_LABEL. */
uint8_t zeros[2]; /* Must be zero. */
ovs_be32 label; /* LABEL */
};
OFP_ASSERT(sizeof(struct nx_action_mpls_label) == 16);

/* Action structure for NXAST_SET_MPLS_TC. */
struct nx_action_mpls_tc {
ovs_be16 type; /* OFPAT_VENDOR. */
ovs_be16 len; /* Length is 8. */
ovs_be32 vendor; /* NX_VENDOR_ID. */
ovs_be16 subtype; /* NXAST_SET_MPLS_TC. */
uint8_t tc; /* TC */
uint8_t pad[5];
};
OFP_ASSERT(sizeof(struct nx_action_mpls_tc) == 16);

/* Action structure for NXAST_SET_MPLS_TTL. */
struct nx_action_mpls_ttl {
ovs_be16 type; /* OFPAT_VENDOR. */
Expand Down
85 changes: 83 additions & 2 deletions lib/ofp-actions.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ union ofp_action {
struct ofp11_action_push push;
struct ofp11_action_pop_mpls ofp11_pop_mpls;
struct ofp11_action_set_queue ofp11_set_queue;
struct ofp11_action_mpls_label ofp11_mpls_label;
struct ofp11_action_mpls_tc ofp11_mpls_tc;
struct ofp11_action_mpls_ttl ofp11_mpls_ttl;
struct ofp11_action_group group;
struct ofp12_action_set_field set_field;
Expand All @@ -77,6 +79,8 @@ union ofp_action {
struct nx_action_pop_mpls pop_mpls;
struct nx_action_sample sample;
struct nx_action_learn learn;
struct nx_action_mpls_label mpls_label;
struct nx_action_mpls_tc mpls_tc;
};

static enum ofperr
Expand Down Expand Up @@ -473,6 +477,14 @@ ofpact_from_nxast(const union ofp_action *a, enum ofputil_action_code code,
OFPACT_MPLS_AFTER_VLAN, out);
break;

case OFPUTIL_NXAST_SET_MPLS_LABEL:
ofpact_put_SET_MPLS_LABEL(out)->label = a->mpls_label.label;
break;

case OFPUTIL_NXAST_SET_MPLS_TC:
ofpact_put_SET_MPLS_TC(out)->tc = a->mpls_tc.tc;
break;

case OFPUTIL_NXAST_SET_MPLS_TTL:
ofpact_put_SET_MPLS_TTL(out)->ttl = a->mpls_ttl.ttl;
break;
Expand Down Expand Up @@ -927,6 +939,15 @@ set_field_to_openflow11(const struct ofpact_set_field *sf,
sf->value.mac, ETH_ADDR_LEN);
break;

case MFF_MPLS_LABEL:
ofputil_put_OFPAT11_SET_MPLS_LABEL(openflow)->mpls_label =
sf->value.be32;
break;

case MFF_MPLS_TC:
ofputil_put_OFPAT11_SET_MPLS_TC(openflow)->mpls_tc = sf->value.u8;
break;

case MFF_IPV4_SRC:
ofputil_put_OFPAT11_SET_NW_SRC(openflow)->nw_addr = sf->value.be32;
break;
Expand Down Expand Up @@ -963,8 +984,6 @@ set_field_to_openflow11(const struct ofpact_set_field *sf,
ofputil_put_OFPAT11_SET_TP_DST(openflow)->tp_port = sf->value.be16;
break;

case MFF_MPLS_TC: /* XXX */
case MFF_MPLS_LABEL: /* XXX */
default:
set_field_to_nxast(sf, openflow);
break;
Expand Down Expand Up @@ -1220,6 +1239,14 @@ ofpact_from_openflow11(const union ofp_action *a, enum ofp_version version,
case OFPUTIL_OFPAT12_SET_FIELD:
return set_field_from_openflow(&a->set_field, out);

case OFPUTIL_OFPAT11_SET_MPLS_LABEL:
ofpact_put_SET_MPLS_LABEL(out)->label = a->ofp11_mpls_label.mpls_label;
break;

case OFPUTIL_OFPAT11_SET_MPLS_TC:
ofpact_put_SET_MPLS_TC(out)->tc = a->ofp11_mpls_tc.mpls_tc;
break;

case OFPUTIL_OFPAT11_SET_MPLS_TTL:
ofpact_put_SET_MPLS_TTL(out)->ttl = a->ofp11_mpls_ttl.mpls_ttl;
break;
Expand Down Expand Up @@ -1273,6 +1300,8 @@ ofpact_is_set_action(const struct ofpact *a)
case OFPACT_SET_IPV4_SRC:
case OFPACT_SET_L4_DST_PORT:
case OFPACT_SET_L4_SRC_PORT:
case OFPACT_SET_MPLS_LABEL:
case OFPACT_SET_MPLS_TC:
case OFPACT_SET_MPLS_TTL:
case OFPACT_SET_QUEUE:
case OFPACT_SET_TUNNEL:
Expand Down Expand Up @@ -1337,6 +1366,8 @@ ofpact_is_allowed_in_actions_set(const struct ofpact *a)
case OFPACT_SET_IPV4_SRC:
case OFPACT_SET_L4_DST_PORT:
case OFPACT_SET_L4_SRC_PORT:
case OFPACT_SET_MPLS_LABEL:
case OFPACT_SET_MPLS_TC:
case OFPACT_SET_MPLS_TTL:
case OFPACT_SET_QUEUE:
case OFPACT_SET_TUNNEL:
Expand Down Expand Up @@ -1586,6 +1617,8 @@ ovs_instruction_type_from_ofpact_type(enum ofpact_type type)
case OFPACT_STACK_PUSH:
case OFPACT_STACK_POP:
case OFPACT_DEC_TTL:
case OFPACT_SET_MPLS_LABEL:
case OFPACT_SET_MPLS_TC:
case OFPACT_SET_MPLS_TTL:
case OFPACT_DEC_MPLS_TTL:
case OFPACT_PUSH_MPLS:
Expand Down Expand Up @@ -1990,6 +2023,8 @@ ofpact_check__(struct ofpact *a, struct flow *flow,
case OFPACT_STACK_POP:
return nxm_stack_pop_check(ofpact_get_STACK_POP(a), flow);

case OFPACT_SET_MPLS_LABEL:
case OFPACT_SET_MPLS_TC:
case OFPACT_SET_MPLS_TTL:
case OFPACT_DEC_MPLS_TTL:
if (!eth_type_mpls(flow->dl_type)) {
Expand Down Expand Up @@ -2313,6 +2348,16 @@ ofpact_to_nxast(const struct ofpact *a, struct ofpbuf *out)
ofpact_dec_ttl_to_nxast(ofpact_get_DEC_TTL(a), out);
break;

case OFPACT_SET_MPLS_LABEL:
ofputil_put_NXAST_SET_MPLS_LABEL(out)->label
= ofpact_get_SET_MPLS_LABEL(a)->label;
break;

case OFPACT_SET_MPLS_TC:
ofputil_put_NXAST_SET_MPLS_TC(out)->tc
= ofpact_get_SET_MPLS_TC(a)->tc;
break;

case OFPACT_SET_MPLS_TTL:
ofputil_put_NXAST_SET_MPLS_TTL(out)->ttl
= ofpact_get_SET_MPLS_TTL(a)->ttl;
Expand Down Expand Up @@ -2516,6 +2561,8 @@ ofpact_to_openflow10(const struct ofpact *a, struct ofpbuf *out)
case OFPACT_DEC_TTL:
case OFPACT_SET_IP_ECN:
case OFPACT_SET_IP_TTL:
case OFPACT_SET_MPLS_LABEL:
case OFPACT_SET_MPLS_TC:
case OFPACT_SET_MPLS_TTL:
case OFPACT_DEC_MPLS_TTL:
case OFPACT_SET_TUNNEL:
Expand Down Expand Up @@ -2659,6 +2706,16 @@ ofpact_to_openflow11(const struct ofpact *a, struct ofpbuf *out)
ofpact_dec_ttl_to_openflow11(ofpact_get_DEC_TTL(a), out);
break;

case OFPACT_SET_MPLS_LABEL:
ofputil_put_OFPAT11_SET_MPLS_LABEL(out)->mpls_label
= ofpact_get_SET_MPLS_LABEL(a)->label;
break;

case OFPACT_SET_MPLS_TC:
ofputil_put_OFPAT11_SET_MPLS_TC(out)->mpls_tc
= ofpact_get_SET_MPLS_TC(a)->tc;
break;

case OFPACT_SET_MPLS_TTL:
ofputil_put_OFPAT11_SET_MPLS_TTL(out)->mpls_ttl
= ofpact_get_SET_MPLS_TTL(a)->ttl;
Expand Down Expand Up @@ -2743,6 +2800,8 @@ ofpact_to_openflow12(const struct ofpact *a, struct ofpbuf *out)
case OFPACT_SET_IP_ECN:
case OFPACT_SET_L4_SRC_PORT:
case OFPACT_SET_L4_DST_PORT:
case OFPACT_SET_MPLS_LABEL:
case OFPACT_SET_MPLS_TC:
case OFPACT_SET_TUNNEL: /* Convert to a set_field, too. */

switch ((int)a->type) {
Expand Down Expand Up @@ -2824,6 +2883,16 @@ ofpact_to_openflow12(const struct ofpact *a, struct ofpbuf *out)
value.be16 = htons(l4port->port);
break;

case OFPACT_SET_MPLS_LABEL:
field = MFF_MPLS_LABEL;
value.be32 = ofpact_get_SET_MPLS_LABEL(a)->label;
break;

case OFPACT_SET_MPLS_TC:
field = MFF_MPLS_TC;
value.u8 = ofpact_get_SET_MPLS_TC(a)->tc;
break;

case OFPACT_SET_TUNNEL:
field = MFF_TUN_ID;
value.be64 = htonll(ofpact_get_SET_TUNNEL(a)->tun_id);
Expand Down Expand Up @@ -3008,6 +3077,8 @@ ofpact_outputs_to_port(const struct ofpact *ofpact, ofp_port_t port)
case OFPACT_STACK_PUSH:
case OFPACT_STACK_POP:
case OFPACT_DEC_TTL:
case OFPACT_SET_MPLS_LABEL:
case OFPACT_SET_MPLS_TC:
case OFPACT_SET_MPLS_TTL:
case OFPACT_DEC_MPLS_TTL:
case OFPACT_SET_TUNNEL:
Expand Down Expand Up @@ -3315,6 +3386,16 @@ ofpact_format(const struct ofpact *a, struct ds *s)
print_dec_ttl(ofpact_get_DEC_TTL(a), s);
break;

case OFPACT_SET_MPLS_LABEL:
ds_put_format(s, "set_mpls_label(%"PRIu32")",
ntohl(ofpact_get_SET_MPLS_LABEL(a)->label));
break;

case OFPACT_SET_MPLS_TC:
ds_put_format(s, "set_mpls_ttl(%"PRIu8")",
ofpact_get_SET_MPLS_TC(a)->tc);
break;

case OFPACT_SET_MPLS_TTL:
ds_put_format(s, "set_mpls_ttl(%"PRIu8")",
ofpact_get_SET_MPLS_TTL(a)->ttl);
Expand Down
22 changes: 21 additions & 1 deletion lib/ofp-actions.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@
DEFINE_OFPACT(STACK_PUSH, ofpact_stack, ofpact) \
DEFINE_OFPACT(STACK_POP, ofpact_stack, ofpact) \
DEFINE_OFPACT(DEC_TTL, ofpact_cnt_ids, cnt_ids) \
DEFINE_OFPACT(SET_MPLS_LABEL, ofpact_mpls_label, ofpact) \
DEFINE_OFPACT(SET_MPLS_TC, ofpact_mpls_tc, ofpact) \
DEFINE_OFPACT(SET_MPLS_TTL, ofpact_mpls_ttl, ofpact) \
DEFINE_OFPACT(DEC_MPLS_TTL, ofpact_null, ofpact) \
DEFINE_OFPACT(PUSH_MPLS, ofpact_push_mpls, ofpact) \
Expand Down Expand Up @@ -552,9 +554,27 @@ struct ofpact_cnt_ids {
uint16_t cnt_ids[];
};

/* OFPACT_SET_MPLS_LABEL.
*
* Used for OFPAT11_SET_MPLS_LABEL and NXAST_SET_MPLS_LABEL */
struct ofpact_mpls_label {
struct ofpact ofpact;

ovs_be32 label;
};

/* OFPACT_SET_MPLS_TC.
*
* Used for OFPAT11_SET_MPLS_TC and NXAST_SET_MPLS_TC */
struct ofpact_mpls_tc {
struct ofpact ofpact;

uint8_t tc;
};

/* OFPACT_SET_MPLS_TTL.
*
* Used for NXAST_SET_MPLS_TTL */
* Used for OFPAT11_SET_MPLS_TTL and NXAST_SET_MPLS_TTL */
struct ofpact_mpls_ttl {
struct ofpact ofpact;

Expand Down
46 changes: 46 additions & 0 deletions lib/ofp-parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,42 @@ parse_dec_ttl(struct ofpbuf *b, char *arg)
return NULL;
}

/* Parses 'arg' as the argument to a "set_mpls_label" action, and appends such
* an action to 'b'.
*
* Returns NULL if successful, otherwise a malloc()'d string describing the
* error. The caller is responsible for freeing the returned string. */
static char * WARN_UNUSED_RESULT
parse_set_mpls_label(struct ofpbuf *b, const char *arg)
{
struct ofpact_mpls_label *mpls_label = ofpact_put_SET_MPLS_LABEL(b);

if (*arg == '\0') {
return xstrdup("parse_set_mpls_label: expected label.");
}

mpls_label->label = htonl(atoi(arg));
return NULL;
}

/* Parses 'arg' as the argument to a "set_mpls_tc" action, and appends such an
* action to 'b'.
*
* Returns NULL if successful, otherwise a malloc()'d string describing the
* error. The caller is responsible for freeing the returned string. */
static char * WARN_UNUSED_RESULT
parse_set_mpls_tc(struct ofpbuf *b, const char *arg)
{
struct ofpact_mpls_tc *mpls_tc = ofpact_put_SET_MPLS_TC(b);

if (*arg == '\0') {
return xstrdup("parse_set_mpls_tc: expected tc.");
}

mpls_tc->tc = atoi(arg);
return NULL;
}

/* Parses 'arg' as the argument to a "set_mpls_ttl" action, and appends such an
* action to 'ofpacts'.
*
Expand Down Expand Up @@ -811,6 +847,16 @@ parse_named_action(enum ofputil_action_code code,
error = parse_dec_ttl(ofpacts, arg);
break;

case OFPUTIL_NXAST_SET_MPLS_LABEL:
case OFPUTIL_OFPAT11_SET_MPLS_LABEL:
error = parse_set_mpls_label(ofpacts, arg);
break;

case OFPUTIL_NXAST_SET_MPLS_TC:
case OFPUTIL_OFPAT11_SET_MPLS_TC:
error = parse_set_mpls_tc(ofpacts, arg);
break;

case OFPUTIL_NXAST_SET_MPLS_TTL:
case OFPUTIL_OFPAT11_SET_MPLS_TTL:
error = parse_set_mpls_ttl(ofpacts, arg);
Expand Down
24 changes: 16 additions & 8 deletions lib/ofp-util.c
Original file line number Diff line number Diff line change
Expand Up @@ -436,11 +436,11 @@ ofputil_match_from_ofp11_match(const struct ofp11_match *ofmatch,
}

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) {
/* MPLS not supported. */
return OFPERR_OFPBMC_BAD_TAG;
if (!(wc & OFPFW11_MPLS_LABEL)) {
match_set_mpls_label(match, ofmatch->mpls_label);
}
if (!(wc & OFPFW11_MPLS_TC)) {
match_set_mpls_tc(match, ofmatch->mpls_tc);
}
}

Expand Down Expand Up @@ -533,9 +533,17 @@ ofputil_match_to_ofp11_match(const struct match *match,
ofmatch->tp_dst = match->flow.tp_dst;
}

/* MPLS not supported. */
wc |= OFPFW11_MPLS_LABEL;
wc |= OFPFW11_MPLS_TC;
if (!(match->wc.masks.mpls_lse & htonl(MPLS_LABEL_MASK))) {
wc |= OFPFW11_MPLS_LABEL;
} else {
ofmatch->mpls_label = htonl(mpls_lse_to_label(match->flow.mpls_lse));
}

if (!(match->wc.masks.mpls_lse & htonl(MPLS_TC_MASK))) {
wc |= OFPFW11_MPLS_TC;
} else {
ofmatch->mpls_tc = mpls_lse_to_tc(match->flow.mpls_lse);
}

ofmatch->metadata = match->flow.metadata;
ofmatch->metadata_mask = ~match->wc.masks.metadata;
Expand Down
4 changes: 4 additions & 0 deletions lib/ofp-util.def
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ OFPAT11_ACTION(OFPAT11_SET_NW_TOS, ofp_action_nw_tos, 0, "mod_nw_tos")
OFPAT11_ACTION(OFPAT11_SET_NW_ECN, ofp11_action_nw_ecn, 0, "mod_nw_ecn")
OFPAT11_ACTION(OFPAT11_SET_TP_SRC, ofp_action_tp_port, 0, "mod_tp_src")
OFPAT11_ACTION(OFPAT11_SET_TP_DST, ofp_action_tp_port, 0, "mod_tp_dst")
OFPAT11_ACTION(OFPAT11_SET_MPLS_LABEL, ofp11_action_mpls_label, 0, "set_mpls_label")
OFPAT11_ACTION(OFPAT11_SET_MPLS_TC, ofp11_action_mpls_tc, 0, "set_mpls_tc")
OFPAT11_ACTION(OFPAT11_SET_MPLS_TTL, ofp11_action_mpls_ttl, 0, "set_mpls_ttl")
OFPAT11_ACTION(OFPAT11_DEC_MPLS_TTL, ofp_action_header, 0, "dec_mpls_ttl")
OFPAT11_ACTION(OFPAT11_PUSH_VLAN, ofp11_action_push, 0, "push_vlan")
Expand Down Expand Up @@ -68,6 +70,8 @@ NXAST_ACTION(NXAST_CONTROLLER, nx_action_controller, 0, "controller")
NXAST_ACTION(NXAST_DEC_TTL_CNT_IDS, nx_action_cnt_ids, 1, NULL)
NXAST_ACTION(NXAST_WRITE_METADATA, nx_action_write_metadata, 0,
"write_metadata")
NXAST_ACTION(NXAST_SET_MPLS_LABEL, nx_action_mpls_label, 0, "set_mpls_label")
NXAST_ACTION(NXAST_SET_MPLS_TC, nx_action_mpls_tc, 0, "set_mpls_tc")
NXAST_ACTION(NXAST_SET_MPLS_TTL, nx_action_mpls_ttl, 0, "set_mpls_ttl")
NXAST_ACTION(NXAST_DEC_MPLS_TTL, nx_action_header, 0, "dec_mpls_ttl")
NXAST_ACTION(NXAST_PUSH_MPLS, nx_action_push_mpls, 0, "push_mpls")
Expand Down
Loading

0 comments on commit 097d493

Please sign in to comment.