On Thu, Oct 24, 2013 at 01:19:34PM -0700, Jarno Rajahalme wrote:
> Signed-off-by: Jarno Rajahalme <jrajaha...@nicira.com>

This looks good to me.

Reviewed-by: Simon Horman <ho...@verge.net.au>


> ---
> v3: Fix byte order errors.
> 
>  include/openflow/nicira-ext.h |   24 ++++++++++++
>  lib/ofp-actions.c             |   82 
> +++++++++++++++++++++++++++++++++++++++--
>  lib/ofp-actions.h             |   22 ++++++++++-
>  lib/ofp-parse.c               |   46 +++++++++++++++++++++++
>  lib/ofp-util.c                |   24 ++++++++----
>  lib/ofp-util.def              |    4 ++
>  ofproto/ofproto-dpif-xlate.c  |   62 +++++++++++++++++++++++++++++++
>  tests/ovs-ofctl.at            |    9 +++--
>  8 files changed, 256 insertions(+), 17 deletions(-)
> 
> diff --git a/include/openflow/nicira-ext.h b/include/openflow/nicira-ext.h
> index 3362a49..0cd62ea 100644
> --- a/include/openflow/nicira-ext.h
> +++ b/include/openflow/nicira-ext.h
> @@ -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. */
> @@ -2261,6 +2263,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. */
> diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c
> index 4713371..9ef1c12 100644
> --- a/lib/ofp-actions.c
> +++ b/lib/ofp-actions.c
> @@ -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;
> @@ -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
> @@ -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;
> @@ -993,13 +1005,13 @@ set_field_to_openflow(const struct ofpact_set_field 
> *sf,
>              return;
>  
>          case MFF_MPLS_LABEL:
> -            /* ofputil_put_OFPAT11_SET_MPLS_LABEL(openflow)->label =
> -               sf->value.be32; */
> +            ofputil_put_OFPAT11_SET_MPLS_LABEL(openflow)->mpls_label =
> +                sf->value.be32;
>              break;
>  
>          case MFF_MPLS_TC:
> -            /* ofputil_put_OFPAT11_SET_MPLS_TC(openflow)->tc =
> -               sf->value.u8; */
> +            ofputil_put_OFPAT11_SET_MPLS_TC(openflow)->mpls_tc =
> +                sf->value.u8;
>              break;
>  
>          case MFF_IPV4_SRC:
> @@ -1220,6 +1232,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;
> @@ -1273,6 +1293,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:
> @@ -1337,6 +1359,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:
> @@ -1586,6 +1610,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:
> @@ -1961,6 +1987,8 @@ ofpact_check__(struct ofpact *a, struct flow *flow, 
> ofp_port_t max_ports,
>      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)) {
> @@ -2280,6 +2308,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;
> @@ -2483,6 +2521,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:
> @@ -2626,6 +2666,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;
> @@ -2710,6 +2760,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) {
> @@ -2791,6 +2843,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);
> @@ -2975,6 +3037,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:
> @@ -3291,6 +3355,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);
> diff --git a/lib/ofp-actions.h b/lib/ofp-actions.h
> index 41579ce..a17688f 100644
> --- a/lib/ofp-actions.h
> +++ b/lib/ofp-actions.h
> @@ -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)    \
> @@ -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;
>  
> diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c
> index 7b19dc0..5ad2255 100644
> --- a/lib/ofp-parse.c
> +++ b/lib/ofp-parse.c
> @@ -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'.
>   *
> @@ -815,6 +851,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);
> diff --git a/lib/ofp-util.c b/lib/ofp-util.c
> index f090539..8828eab 100644
> --- a/lib/ofp-util.c
> +++ b/lib/ofp-util.c
> @@ -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);
>          }
>      }
>  
> @@ -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;
> diff --git a/lib/ofp-util.def b/lib/ofp-util.def
> index 631a6b1..fae2bf2 100644
> --- a/lib/ofp-util.def
> +++ b/lib/ofp-util.def
> @@ -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")
> @@ -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")
> diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
> index 94c7eec..7626dcb 100644
> --- a/ofproto/ofproto-dpif-xlate.c
> +++ b/ofproto/ofproto-dpif-xlate.c
> @@ -1984,6 +1984,54 @@ compose_dec_ttl(struct xlate_ctx *ctx, struct 
> ofpact_cnt_ids *ids)
>  }
>  
>  static bool
> +compose_set_mpls_label_action(struct xlate_ctx *ctx, ovs_be32 label)
> +{
> +    if (!eth_type_mpls(ctx->xin->flow.dl_type)) {
> +        return true;
> +    }
> +
> +    /* If mpls_depth_delta is negative then an MPLS POP action has been
> +     * executed and the resulting MPLS label stack is unknown.  This means
> +     * a SET MPLS LABEL action can't be executed as it needs to manipulate
> +     * the top-most MPLS LSE. Thus, stop processing.
> +     *
> +     * It is planned that in the future this case will be handled
> +     * by recirculation.
> +     */
> +    if (ctx->mpls_depth_delta < 0) {
> +        return true;
> +    }
> +
> +    ctx->xout->wc.masks.mpls_lse |= htonl(MPLS_LABEL_MASK);
> +    set_mpls_lse_label(&ctx->xin->flow.mpls_lse, label);
> +    return false;
> +}
> +
> +static bool
> +compose_set_mpls_tc_action(struct xlate_ctx *ctx, uint8_t tc)
> +{
> +    if (!eth_type_mpls(ctx->xin->flow.dl_type)) {
> +        return true;
> +    }
> +
> +    /* If mpls_depth_delta is negative then an MPLS POP action has been
> +     * executed and the resulting MPLS label stack is unknown.  This means
> +     * a SET MPLS TC action can't be executed as it needs to manipulate
> +     * the top-most MPLS LSE. Thus, stop processing.
> +     *
> +     * It is planned that in the future this case will be handled
> +     * by recirculation.
> +     */
> +    if (ctx->mpls_depth_delta < 0) {
> +        return true;
> +    }
> +
> +    ctx->xout->wc.masks.mpls_lse |= htonl(MPLS_TC_MASK);
> +    set_mpls_lse_tc(&ctx->xin->flow.mpls_lse, tc);
> +    return false;
> +}
> +
> +static bool
>  compose_set_mpls_ttl_action(struct xlate_ctx *ctx, uint8_t ttl)
>  {
>      if (!eth_type_mpls(ctx->xin->flow.dl_type)) {
> @@ -2476,6 +2524,20 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t 
> ofpacts_len,
>              }
>              break;
>  
> +        case OFPACT_SET_MPLS_LABEL:
> +            if (compose_set_mpls_label_action(ctx,
> +                                              
> ofpact_get_SET_MPLS_LABEL(a)->label)) {
> +                return;
> +            }
> +            break;
> +
> +        case OFPACT_SET_MPLS_TC:
> +            if (compose_set_mpls_tc_action(ctx,
> +                                           ofpact_get_SET_MPLS_TC(a)->tc)) {
> +                return;
> +            }
> +            break;
> +
>          case OFPACT_SET_MPLS_TTL:
>              if (compose_set_mpls_ttl_action(ctx,
>                                              
> ofpact_get_SET_MPLS_TTL(a)->ttl)) {
> diff --git a/tests/ovs-ofctl.at b/tests/ovs-ofctl.at
> index d503149..530c633 100644
> --- a/tests/ovs-ofctl.at
> +++ b/tests/ovs-ofctl.at
> @@ -1517,15 +1517,16 @@ dnl Ignore tp_dst if not TCP/UDP/SCTP:
>  0000 00 00 0800 00 16 00000000ffffffff 00000000ffffffff 0000 01bb dnl
>  00000000 00 000000 0000000000000000ffffffffffffffff
>  
> -dnl mpls_label not yet supported:
> -# bad ofp11_match: OFPBMC_BAD_TAG
> +# mpls,mpls_label=284280
> +# 64: 12 -> 00
> +# 65: 34 -> 04
>  0000 0058 00000000 000002f7 dnl
>  000000000000ffffffffffff 000000000000ffffffffffff dnl
>  0000 00 00 8847 00 00 00000000ffffffff 00000000ffffffff 0000 0000 dnl
>  12345678 00 000000 0000000000000000ffffffffffffffff
>  
> -dnl mpls_tc not yet supported:
> -# bad ofp11_match: OFPBMC_BAD_TAG
> +# mplsm,mpls_tc=2
> +# 68: 5a -> 02
>  0000 0058 00000000 000001f7 dnl
>  000000000000ffffffffffff 000000000000ffffffffffff dnl
>  0000 00 00 8848 00 00 00000000ffffffff 00000000ffffffff 0000 0000 dnl
> -- 
> 1.7.10.4
> 
> _______________________________________________
> dev mailing list
> dev@openvswitch.org
> http://openvswitch.org/mailman/listinfo/dev
> 
_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to