Message ID | 1382711684-17080-2-git-send-email-horms@verge.net.au |
---|---|
State | Not Applicable, archived |
Delegated to: | David Miller |
Headers | show |
On Fri, Oct 25, 2013 at 03:34:41PM +0100, Simon Horman wrote: > From: Joe Stringer <joe@wand.net.nz> > > OpenFlow 1.1 and 1.2, and 1.3 differ in their handling of MPLS actions in the > presence of VLAN tags. To allow correct behaviour to be committed in > each situation, this patch adds a second round of VLAN tag action > handling to commit_odp_actions(), which occurs after MPLS actions. This > is implemented with a new field in 'struct xlate_in' called 'vlan_tci'. > > When an push_mpls action is composed, the flow's current VLAN state is > stored into xin->vlan_tci, and flow->vlan_tci is set to 0 (pop_vlan). If > a VLAN tag is present, it is stripped; if not, then there is no change. > Any later modifications to the VLAN state is written to xin->vlan_tci. > When committing the actions, flow->vlan_tci is used before MPLS actions, > and xin->vlan_tci is used afterwards. This retains the current datapath > behaviour, but allows VLAN actions to be applied in a more flexible > manner. > > Both before and after this patch MPLS LSEs are pushed onto a packet after > any VLAN tags that may be present. This is the behaviour described in > OpenFlow 1.1 and 1.2. OpenFlow 1.3 specifies that MPLS LSEs should be > pushed onto a packet before any VLAN tags that are present. Support > for this will be added by a subsequent patch that makes use of > the infrastructure added by this patch. Whole changelog message still reflects the intent of the code the implementation details it describes are no longer correct. I will fix this and re-post. > > Signed-off-by: Joe Stringer <joe@wand.net.nz> > Signed-off-by: Simon Horman <horms@verge.net.au> > > --- > > v2.45 [Simon Horman] > * As pointed out by Ben Pfaff and Joe Stringer > + Update VLAN handling in the presence of MPLS push > > Previously the test for committing ODP VLAN actions after MPLS actions > was that the VLAN TCI differed before and after the MPLS push action. > This results in a false negative in some cases including if a VLAN tag > is pushed after the MPLS push action in such a way that it duplicates > the VLAN tag present before the MPLS push action. > > This is resolved by ensuring the VLAN_CFI bit of the value used to > track the desired VLAN TCI after an MPLS push action is zero unless > VLAN actions should be committed after MPLS actions. > > + Update tests to use ovs-ofctl monitor "-m" to allow full inspection of > MPLS LSE and VLAN tags present in packets. > > v2.44 [Simon Horman] > * Rebase for the following changes: > f47ea02 ("Set datapath mask bits when setting a flow field.") > 7fdb60a ("Add support for write-actions") > 7358063 ("odp-util: Elaborate the comment for odp_flow_format() function.") > * Correct final_vlan_tci and next_vlan_tci initialisation in xlate_actions__() > > v2.43 [Simon Horman] > * As suggested by Ben Pfaff > Move vlan state into struct xlate_ctx > > 1. Add final_vlan_tci member to struct xlate_ctx instead of vlan_tci member > struct xlate_xin. This seems to be a better palace for it as it does > not need to be accessible from the caller. > > 2. Move local vlan_tci variable of do_xlate_actions() to be the > next_vlan_tci member of strict xlate_ctx. This allows for it to work > across resubmit actions and goto table instructions. > > v2.42 > * No change > > v2.41 [Joe Stringer via Simon Horman] > * Rework comments to make things a little clearer > > v2.40 [Simon Horman] > * Rebase for removal of mpls_depth from struct flow > > v2.38 - v2.39 > * No change > > v2.37 > * Rebase > > v2.36 > * No change > > v2.5 [Joe Stringer] > * First post > --- > lib/odp-util.c | 12 +- > lib/odp-util.h | 3 +- > ofproto/ofproto-dpif-xlate.c | 136 ++++++++++++--- > tests/ofproto-dpif.at | 389 +++++++++++++++++++++++++++++++++++++++++++ > 4 files changed, 514 insertions(+), 26 deletions(-) > > diff --git a/lib/odp-util.c b/lib/odp-util.c > index 6875e01..21b33ac 100644 > --- a/lib/odp-util.c > +++ b/lib/odp-util.c > @@ -3639,11 +3639,15 @@ commit_set_pkt_mark_action(const struct flow *flow, struct flow *base, > * used as part of the action. > * > * Returns a reason to force processing the flow's packets into the userspace > - * slow path, if there is one, otherwise 0. */ > + * slow path, if there is one, otherwise 0. > + * > + * VLAN actions may be committed twice; If vlan_tci in 'flow' differs from the > + * one in 'base', then it is committed before MPLS actions. If the VLAN_CFI > + * bit of 'post_mpls_vlan_tci' is set then it is committed afterwards. */ > enum slow_path_reason > commit_odp_actions(const struct flow *flow, struct flow *base, > struct ofpbuf *odp_actions, struct flow_wildcards *wc, > - int *mpls_depth_delta) > + int *mpls_depth_delta, ovs_be16 post_mpls_vlan_tci) > { > enum slow_path_reason slow; > > @@ -3656,6 +3660,10 @@ commit_odp_actions(const struct flow *flow, struct flow *base, > * that it is no longer IP and thus nw and port actions are no longer valid. > */ > commit_mpls_action(flow, base, odp_actions, wc, mpls_depth_delta); > + if (post_mpls_vlan_tci & htons(VLAN_CFI)) { > + base->vlan_tci = htons(0); > + commit_vlan_action(post_mpls_vlan_tci, base, odp_actions, wc); > + } > commit_set_priority_action(flow, base, odp_actions, wc); > commit_set_pkt_mark_action(flow, base, odp_actions, wc); > > diff --git a/lib/odp-util.h b/lib/odp-util.h > index 821b2c4..636a3ec 100644 > --- a/lib/odp-util.h > +++ b/lib/odp-util.h > @@ -175,7 +175,8 @@ enum slow_path_reason commit_odp_actions(const struct flow *, > struct flow *base, > struct ofpbuf *odp_actions, > struct flow_wildcards *wc, > - int *mpls_depth_delta); > + int *mpls_depth_delta, > + ovs_be16 post_mpls_vlan_tci); > > /* ofproto-dpif interface. > * > diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c > index 7be691c..d79356f 100644 > --- a/ofproto/ofproto-dpif-xlate.c > +++ b/ofproto/ofproto-dpif-xlate.c > @@ -180,6 +180,37 @@ struct xlate_ctx { > uint16_t user_cookie_offset;/* Used for user_action_cookie fixup. */ > bool exit; /* No further actions should be processed. */ > > + /* The post MPLS vlan_tci. > + * > + * The value of the vlan TCI prior to the translation of an MPLS push > + * actions should be stored in 'xin->flow->vlan_tci'. > + * > + * If an VLAN or set field action is subsequently translated then > + * 'post_mpls_vlan_tci' is updated as according to the action. > + * > + * If the VLAN_CFI bit of 'post_mpls_vlan_tci' is set then VLAN ODP actions > + * will be committed after any MPLS actions regardless of whether VLAN > + * actions were also committed before the MPLS actions or not. > + * > + * This mechanism allows a VLAN tag to be popped before pushing > + * an MPLS LSE and then the same VLAN tag pushed after pushing > + * the MPLS LSE. In this way it is possible to push an MPLS LSE > + * after an existing VLAN tag. Moreover this mechanism allows > + * the order in which VLAN tags and MPLS LSEs are pushed. */ > + ovs_be16 post_mpls_vlan_tci; > + > + /* The next vlan_tci state. > + * > + * This field pints to the variable update each time an > + * action updates the VLAN tci. > + * > + * This variable initially points to 'xin->flow->vlan_tci' so that ODP > + * VLAN actions are committed before any MPLS actions. When an MPLS > + * action is composed 'next_vlan_tci' is updated to point to > + * 'post_mpls_vlan_tci'. This causes subsequent VLAN actions to be > + * committed after MPLS actions. */ > + ovs_be16 *next_vlan_tci; > + > /* OpenFlow 1.1+ action set. > * > * 'action_set' accumulates "struct ofpact"s added by OFPACT_WRITE_ACTIONS. > @@ -996,11 +1027,38 @@ output_vlan_to_vid(const struct xbundle *out_xbundle, uint16_t vlan) > } > } > > +static bool mpls_actions_xlated(struct xlate_ctx *ctx) > +{ > + return ctx->next_vlan_tci == &ctx->post_mpls_vlan_tci; > +} > + > +static ovs_be16 > +vlan_tci_save(struct xlate_ctx *ctx) > +{ > + ovs_be16 orig_tci = ctx->xin->flow.vlan_tci; > + /* If MPLS actions were executed after vlan actions then > + * copy the final vlan_tci out and restore the intermediate VLAN state. */ > + if (mpls_actions_xlated(ctx)) { > + ctx->xin->flow.vlan_tci = *ctx->next_vlan_tci; > + } > + return orig_tci; > +} > + > +static void > +vlan_tci_restore(struct xlate_ctx *ctx, ovs_be16 orig_tci) > +{ > + /* If MPLS actions were executed after vlan actions then > + * copy the final vlan_tci out and restore the intermediate VLAN state. */ > + if (mpls_actions_xlated(ctx)) { > + ctx->post_mpls_vlan_tci = ctx->xin->flow.vlan_tci; > + ctx->xin->flow.vlan_tci = orig_tci; > + } > +} > + > static void > output_normal(struct xlate_ctx *ctx, const struct xbundle *out_xbundle, > uint16_t vlan) > { > - ovs_be16 *flow_tci = &ctx->xin->flow.vlan_tci; > uint16_t vid; > ovs_be16 tci, old_tci; > struct xport *xport; > @@ -1025,18 +1083,18 @@ output_normal(struct xlate_ctx *ctx, const struct xbundle *out_xbundle, > } > } > > - old_tci = *flow_tci; > + old_tci = *ctx->next_vlan_tci; > tci = htons(vid); > if (tci || out_xbundle->use_priority_tags) { > - tci |= *flow_tci & htons(VLAN_PCP_MASK); > + tci |= *ctx->next_vlan_tci & htons(VLAN_PCP_MASK); > if (tci) { > tci |= htons(VLAN_CFI); > } > } > - *flow_tci = tci; > + ctx->xin->flow.vlan_tci = *ctx->next_vlan_tci = tci; > > compose_output_action(ctx, xport->ofp_port); > - *flow_tci = old_tci; > + ctx->xin->flow.vlan_tci = *ctx->next_vlan_tci = old_tci; > } > > /* A VM broadcasts a gratuitous ARP to indicate that it has resumed after > @@ -1269,7 +1327,7 @@ xlate_normal(struct xlate_ctx *ctx) > > /* Drop malformed frames. */ > if (flow->dl_type == htons(ETH_TYPE_VLAN) && > - !(flow->vlan_tci & htons(VLAN_CFI))) { > + !(*ctx->next_vlan_tci & htons(VLAN_CFI))) { > if (ctx->xin->packet != NULL) { > static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); > VLOG_WARN_RL(&rl, "bridge %s: dropping packet with partial " > @@ -1293,7 +1351,7 @@ xlate_normal(struct xlate_ctx *ctx) > } > > /* Check VLAN. */ > - vid = vlan_tci_to_vid(flow->vlan_tci); > + vid = vlan_tci_to_vid(*ctx->next_vlan_tci); > if (!input_vid_is_valid(vid, in_xbundle, ctx->xin->packet != NULL)) { > xlate_report(ctx, "disallowed VLAN VID for this input port, dropping"); > return; > @@ -1551,7 +1609,7 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port, > const struct xport *xport = get_ofp_port(ctx->xbridge, ofp_port); > struct flow_wildcards *wc = &ctx->xout->wc; > struct flow *flow = &ctx->xin->flow; > - ovs_be16 flow_vlan_tci; > + ovs_be16 flow_vlan_tci, vlan_tci; > uint32_t flow_pkt_mark; > uint8_t flow_nw_tos; > odp_port_t out_port, odp_port; > @@ -1620,6 +1678,7 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port, > } > > flow_vlan_tci = flow->vlan_tci; > + vlan_tci = *ctx->next_vlan_tci; > flow_pkt_mark = flow->pkt_mark; > flow_nw_tos = flow->nw_tos; > > @@ -1659,12 +1718,13 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port, > wc->masks.vlan_tci |= htons(VLAN_VID_MASK | VLAN_CFI); > } > vlandev_port = vsp_realdev_to_vlandev(ctx->xbridge->ofproto, ofp_port, > - flow->vlan_tci); > + *ctx->next_vlan_tci); > if (vlandev_port == ofp_port) { > out_port = odp_port; > } else { > out_port = ofp_port_to_odp_port(ctx->xbridge, vlandev_port); > flow->vlan_tci = htons(0); > + ctx->post_mpls_vlan_tci = htons(0); > } > } > > @@ -1672,7 +1732,8 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port, > ctx->xout->slow |= commit_odp_actions(flow, &ctx->base_flow, > &ctx->xout->odp_actions, > &ctx->xout->wc, > - &ctx->mpls_depth_delta); > + &ctx->mpls_depth_delta, > + ctx->post_mpls_vlan_tci); > nl_msg_put_odp_port(&ctx->xout->odp_actions, OVS_ACTION_ATTR_OUTPUT, > out_port); > > @@ -1684,6 +1745,7 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port, > out: > /* Restore flow */ > flow->vlan_tci = flow_vlan_tci; > + *ctx->next_vlan_tci = vlan_tci; > flow->pkt_mark = flow_pkt_mark; > flow->nw_tos = flow_nw_tos; > } > @@ -1838,7 +1900,8 @@ execute_controller_action(struct xlate_ctx *ctx, int len, > ctx->xout->slow |= commit_odp_actions(&ctx->xin->flow, &ctx->base_flow, > &ctx->xout->odp_actions, > &ctx->xout->wc, > - &ctx->mpls_depth_delta); > + &ctx->mpls_depth_delta, > + ctx->post_mpls_vlan_tci); > > odp_execute_actions(NULL, packet, &key, ctx->xout->odp_actions.data, > ctx->xout->odp_actions.size, NULL, NULL); > @@ -2231,7 +2294,8 @@ xlate_sample_action(struct xlate_ctx *ctx, > ctx->xout->slow |= commit_odp_actions(&ctx->xin->flow, &ctx->base_flow, > &ctx->xout->odp_actions, > &ctx->xout->wc, > - &ctx->mpls_depth_delta); > + &ctx->mpls_depth_delta, > + ctx->post_mpls_vlan_tci); > > compose_flow_sample_cookie(os->probability, os->collector_set_id, > os->obs_domain_id, os->obs_point_id, &cookie); > @@ -2320,28 +2384,28 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, > > case OFPACT_SET_VLAN_VID: > wc->masks.vlan_tci |= htons(VLAN_VID_MASK | VLAN_CFI); > - flow->vlan_tci &= ~htons(VLAN_VID_MASK); > - flow->vlan_tci |= (htons(ofpact_get_SET_VLAN_VID(a)->vlan_vid) > - | htons(VLAN_CFI)); > + *ctx->next_vlan_tci &= ~htons(VLAN_VID_MASK); > + *ctx->next_vlan_tci |= (htons(ofpact_get_SET_VLAN_VID(a)->vlan_vid) > + | htons(VLAN_CFI)); > break; > > case OFPACT_SET_VLAN_PCP: > wc->masks.vlan_tci |= htons(VLAN_PCP_MASK | VLAN_CFI); > - flow->vlan_tci &= ~htons(VLAN_PCP_MASK); > - flow->vlan_tci |= > + *ctx->next_vlan_tci &= ~htons(VLAN_PCP_MASK); > + *ctx->next_vlan_tci |= > htons((ofpact_get_SET_VLAN_PCP(a)->vlan_pcp << VLAN_PCP_SHIFT) > | VLAN_CFI); > break; > > case OFPACT_STRIP_VLAN: > memset(&wc->masks.vlan_tci, 0xff, sizeof wc->masks.vlan_tci); > - flow->vlan_tci = htons(0); > + *ctx->next_vlan_tci = htons(0); > break; > > case OFPACT_PUSH_VLAN: > /* XXX 802.1AD(QinQ) */ > memset(&wc->masks.vlan_tci, 0xff, sizeof wc->masks.vlan_tci); > - flow->vlan_tci = htons(VLAN_CFI); > + *ctx->next_vlan_tci = htons(VLAN_CFI); > break; > > case OFPACT_SET_ETH_SRC: > @@ -2423,29 +2487,53 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, > flow->skb_priority = ctx->orig_skb_priority; > break; > > - case OFPACT_REG_MOVE: > + case OFPACT_REG_MOVE: { > + ovs_be16 orig_tci = flow->vlan_tci; > nxm_execute_reg_move(ofpact_get_REG_MOVE(a), flow, wc); > + vlan_tci_restore(ctx, orig_tci); > break; > + } > > - case OFPACT_REG_LOAD: > + case OFPACT_REG_LOAD: { > + ovs_be16 orig_tci = vlan_tci_save(ctx); > nxm_execute_reg_load(ofpact_get_REG_LOAD(a), flow, wc); > + vlan_tci_restore(ctx, orig_tci); > break; > + } > > - case OFPACT_STACK_PUSH: > + case OFPACT_STACK_PUSH: { > + ovs_be16 orig_tci = vlan_tci_save(ctx); > nxm_execute_stack_push(ofpact_get_STACK_PUSH(a), flow, wc, > &ctx->stack); > + vlan_tci_restore(ctx, orig_tci); > break; > + } > > - case OFPACT_STACK_POP: > + case OFPACT_STACK_POP: { > + ovs_be16 orig_tci = vlan_tci_save(ctx); > nxm_execute_stack_pop(ofpact_get_STACK_POP(a), flow, wc, > &ctx->stack); > + vlan_tci_restore(ctx, orig_tci); > break; > + } > > case OFPACT_PUSH_MPLS: > if (compose_mpls_push_action(ctx, > ofpact_get_PUSH_MPLS(a)->ethertype)) { > return; > } > + > + /* Save and pop any existing VLAN tags. They will be pushed > + * back onto the packet after pushing the MPLS LSE. The overall > + * effect is to push the MPLS LSE after any VLAN tags that may > + * be present. This is the behaviour described for OpenFlow 1.1 > + * and 1.2. This code needs to be enhanced to make this > + * conditional to also and support pushing the MPLS LSE before > + * any VLAN tags that may be present, the behaviour described > + * for OpenFlow 1.3. */ > + ctx->post_mpls_vlan_tci = *ctx->next_vlan_tci; > + flow->vlan_tci = htons(0); > + ctx->next_vlan_tci = &ctx->post_mpls_vlan_tci; > break; > > case OFPACT_POP_MPLS: > @@ -2786,6 +2874,8 @@ xlate_actions__(struct xlate_in *xin, struct xlate_out *xout) > ctx.table_id = 0; > ctx.exit = false; > ctx.mpls_depth_delta = 0; > + ctx.post_mpls_vlan_tci = htons(0); > + ctx.next_vlan_tci = &ctx.xin->flow.vlan_tci; > > if (!xin->ofpacts && !ctx.rule) { > rule_dpif_lookup(ctx.xbridge->ofproto, flow, wc, &rule); > diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at > index c569463..372bce7 100644 > --- a/tests/ofproto-dpif.at > +++ b/tests/ofproto-dpif.at > @@ -965,6 +965,395 @@ done > OVS_VSWITCHD_STOP > AT_CLEANUP > > +AT_SETUP([ofproto-dpif - OF1.2 VLAN+MPLS handling]) > +OVS_VSWITCHD_START([dnl > + add-port br0 p1 -- set Interface p1 type=dummy > +]) > +ON_EXIT([kill `cat ovs-ofctl.pid`]) > + > +AT_CAPTURE_FILE([ofctl_monitor.log]) > +AT_DATA([flows.txt], [dnl > +cookie=0xa dl_src=40:44:44:44:54:50 actions=push_mpls:0x8847,load:10->OXM_OF_MPLS_LABEL[[]],push_vlan:0x8100,mod_vlan_vid:99,mod_vlan_pcp:1,controller > +cookie=0xa dl_src=40:44:44:44:54:51 actions=push_mpls:0x8847,load:10->OXM_OF_MPLS_LABEL[[]],push_vlan:0x8100,mod_vlan_vid:99,mod_vlan_pcp:1,controller > +cookie=0xa dl_src=40:44:44:44:54:52 actions=push_mpls:0x8847,load:10->OXM_OF_MPLS_LABEL[[]],push_vlan:0x8100,load:99->OXM_OF_VLAN_VID[[]],mod_vlan_pcp:1,controller > +cookie=0xa dl_src=40:44:44:44:54:53 actions=push_mpls:0x8847,load:10->OXM_OF_MPLS_LABEL[[]],push_vlan:0x8100,load:99->OXM_OF_VLAN_VID[[]],mod_vlan_pcp:1,controller > +cookie=0xa dl_src=40:44:44:44:54:54 actions=push_vlan:0x8100,mod_vlan_vid:99,mod_vlan_pcp:1,push_mpls:0x8847,load:10->OXM_OF_MPLS_LABEL[[]],controller > +cookie=0xa dl_src=40:44:44:44:54:55 actions=push_vlan:0x8100,mod_vlan_vid:99,mod_vlan_pcp:1,push_mpls:0x8847,load:10->OXM_OF_MPLS_LABEL[[]],controller > +cookie=0xa dl_src=40:44:44:44:54:56 actions=push_vlan:0x8100,load:99->OXM_OF_VLAN_VID[[]],mod_vlan_pcp:1,push_mpls:0x8847,load:10->OXM_OF_MPLS_LABEL[[]],controller > +cookie=0xa dl_src=40:44:44:44:54:57 actions=push_vlan:0x8100,load:99->OXM_OF_VLAN_VID[[]],mod_vlan_pcp:1,push_mpls:0x8847,load:10->OXM_OF_MPLS_LABEL[[]],controller > +cookie=0xa dl_src=40:44:44:44:54:58 actions=load:99->OXM_OF_VLAN_VID[[]],mod_vlan_pcp:1,push_mpls:0x8847,load:10->OXM_OF_MPLS_LABEL[[]],controller > +cookie=0xa dl_src=40:44:44:44:54:59 actions=push_mpls:0x8847,load:10->OXM_OF_MPLS_LABEL[[]],mod_vlan_pcp:1,load:99->OXM_OF_VLAN_VID[[]],controller > +]) > +AT_CHECK([ovs-ofctl --protocols=OpenFlow12 add-flows br0 flows.txt]) > + > +dnl Modified MPLS controller action. > +dnl In this test, we push the MPLS tag before pushing a VLAN tag, so we see > +dnl both of these in the final flow > +AT_CHECK([ovs-ofctl monitor br0 65534 -m -P nxm --detach --pidfile 2> ofctl_monitor.log]) > + > +for i in 1 2 3; do > + ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=40:44:44:44:54:50,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no)' > +done > +OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit]) > + > +AT_CHECK([cat ofctl_monitor.log], [0], [dnl > +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=68 in_port=1 (via action) data_len=68 (unbuffered) > +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:50,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 > +00000000 50 54 00 00 00 07 40 44-44 44 54 50 81 00 20 63 > +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 > +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 > +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 > +00000040 00 00 00 00 > +dnl > +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=68 in_port=1 (via action) data_len=68 (unbuffered) > +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:50,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 > +00000000 50 54 00 00 00 07 40 44-44 44 54 50 81 00 20 63 > +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 > +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 > +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 > +00000040 00 00 00 00 > +dnl > +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=68 in_port=1 (via action) data_len=68 (unbuffered) > +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:50,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 > +00000000 50 54 00 00 00 07 40 44-44 44 54 50 81 00 20 63 > +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 > +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 > +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 > +00000040 00 00 00 00 > +]) > + > +dnl Modified MPLS controller action. > +dnl In this test, the input packet in vlan-tagged, which should be stripped > +dnl before we push the MPLS and VLAN tags. > +AT_CHECK([ovs-ofctl monitor br0 65534 -m -P nxm --detach --pidfile 2> ofctl_monitor.log]) > + > +for i in 1 2 3; do > + ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=40:44:44:44:54:51,dst=50:54:00:00:00:07),eth_type(0x8100),vlan(vid=88,pcp=7),encap(eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no))' > +done > +OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6]) > +ovs-appctl -t ovs-ofctl exit > + > +AT_CHECK([cat ofctl_monitor.log], [0], [dnl > +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered) > +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:51,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 > +00000000 50 54 00 00 00 07 40 44-44 44 54 51 81 00 20 63 > +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 > +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 > +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 > +dnl > +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered) > +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:51,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 > +00000000 50 54 00 00 00 07 40 44-44 44 54 51 81 00 20 63 > +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 > +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 > +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 > +dnl > +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered) > +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:51,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 > +00000000 50 54 00 00 00 07 40 44-44 44 54 51 81 00 20 63 > +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 > +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 > +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 > +]) > + > +dnl Modified MPLS controller action. > +dnl In this test, we push the MPLS tag before pushing a VLAN tag, so we see > +dnl both of these in the final flow > +AT_CHECK([ovs-ofctl monitor br0 65534 -m -P nxm --detach --pidfile 2> ofctl_monitor.log]) > + > +for i in 1 2 3; do > + ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=40:44:44:44:54:52,dst=52:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no)' > +done > +OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit]) > + > +AT_CHECK([cat ofctl_monitor.log], [0], [dnl > +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=68 in_port=1 (via action) data_len=68 (unbuffered) > +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:52,dl_dst=52:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 > +00000000 52 54 00 00 00 07 40 44-44 44 54 52 81 00 20 63 > +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 > +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 > +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 > +00000040 00 00 00 00 > +dnl > +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=68 in_port=1 (via action) data_len=68 (unbuffered) > +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:52,dl_dst=52:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 > +00000000 52 54 00 00 00 07 40 44-44 44 54 52 81 00 20 63 > +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 > +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 > +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 > +00000040 00 00 00 00 > +dnl > +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=68 in_port=1 (via action) data_len=68 (unbuffered) > +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:52,dl_dst=52:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 > +00000000 52 54 00 00 00 07 40 44-44 44 54 52 81 00 20 63 > +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 > +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 > +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 > +00000040 00 00 00 00 > +]) > + > +dnl Modified MPLS controller action. > +dnl In this test, the input packet in vlan-tagged, which should be stripped > +dnl before we push the MPLS and VLAN tags. > +AT_CHECK([ovs-ofctl monitor br0 65534 -m -P nxm --detach --pidfile 2> ofctl_monitor.log]) > + > +for i in 1 2 3; do > + ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=40:44:44:44:54:53,dst=50:54:00:00:00:07),eth_type(0x8100),vlan(vid=88,pcp=7),encap(eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no))' > +done > +OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6]) > +ovs-appctl -t ovs-ofctl exit > + > +AT_CHECK([cat ofctl_monitor.log], [0], [dnl > +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered) > +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:53,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 > +00000000 50 54 00 00 00 07 40 44-44 44 54 53 81 00 20 63 > +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 > +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 > +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 > +dnl > +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered) > +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:53,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 > +00000000 50 54 00 00 00 07 40 44-44 44 54 53 81 00 20 63 > +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 > +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 > +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 > +dnl > +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered) > +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:53,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 > +00000000 50 54 00 00 00 07 40 44-44 44 54 53 81 00 20 63 > +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 > +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 > +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 > +]) > + > +dnl Modified MPLS controller action. > +dnl In this test, we push the VLAN tag before pushing a MPLS tag, but these > +dnl actions are reordered, so we see both of these in the final flow. > +AT_CHECK([ovs-ofctl monitor br0 65534 -m -P nxm --detach --pidfile 2> ofctl_monitor.log]) > + > +for i in 1 2 3; do > + ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=40:44:44:44:54:54,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no)' > +done > +OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6]) > +ovs-appctl -t ovs-ofctl exit > + > +AT_CHECK([cat ofctl_monitor.log], [0], [dnl > +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=68 in_port=1 (via action) data_len=68 (unbuffered) > +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:54,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 > +00000000 50 54 00 00 00 07 40 44-44 44 54 54 81 00 20 63 > +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 > +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 > +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 > +00000040 00 00 00 00 > +dnl > +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=68 in_port=1 (via action) data_len=68 (unbuffered) > +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:54,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 > +00000000 50 54 00 00 00 07 40 44-44 44 54 54 81 00 20 63 > +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 > +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 > +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 > +00000040 00 00 00 00 > +dnl > +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=68 in_port=1 (via action) data_len=68 (unbuffered) > +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:54,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 > +00000000 50 54 00 00 00 07 40 44-44 44 54 54 81 00 20 63 > +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 > +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 > +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 > +00000040 00 00 00 00 > +]) > + > +dnl Modified MPLS controller action. > +dnl In this test, the input packet in vlan-tagged, which should be stripped > +dnl before we push the MPLS and VLAN tags. > +AT_CHECK([ovs-ofctl monitor br0 65534 -m -P nxm --detach --pidfile 2> ofctl_monitor.log]) > + > +for i in 1 2 3; do > + ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=40:44:44:44:54:55,dst=50:54:00:00:00:07),eth_type(0x8100),vlan(vid=88,pcp=7),encap(eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no))' > +done > +OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6]) > +ovs-appctl -t ovs-ofctl exit > + > +AT_CHECK([cat ofctl_monitor.log], [0], [dnl > +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered) > +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:55,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 > +00000000 50 54 00 00 00 07 40 44-44 44 54 55 81 00 20 63 > +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 > +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 > +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 > +dnl > +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered) > +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:55,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 > +00000000 50 54 00 00 00 07 40 44-44 44 54 55 81 00 20 63 > +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 > +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 > +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 > +dnl > +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered) > +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:55,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 > +00000000 50 54 00 00 00 07 40 44-44 44 54 55 81 00 20 63 > +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 > +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 > +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 > +]) > + > +dnl Modified MPLS controller action. > +dnl In this test, we push the VLAN tag before pushing a MPLS tag, but these > +dnl actions are reordered, so we see both of these in the final flow. > +AT_CHECK([ovs-ofctl monitor br0 65534 -m -P nxm --detach --pidfile 2> ofctl_monitor.log]) > + > +for i in 1 2 3; do > + ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=40:44:44:44:54:56,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no)' > +done > +OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6]) > +ovs-appctl -t ovs-ofctl exit > + > +AT_CHECK([cat ofctl_monitor.log], [0], [dnl > +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=68 in_port=1 (via action) data_len=68 (unbuffered) > +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:56,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 > +00000000 50 54 00 00 00 07 40 44-44 44 54 56 81 00 20 63 > +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 > +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 > +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 > +00000040 00 00 00 00 > +dnl > +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=68 in_port=1 (via action) data_len=68 (unbuffered) > +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:56,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 > +00000000 50 54 00 00 00 07 40 44-44 44 54 56 81 00 20 63 > +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 > +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 > +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 > +00000040 00 00 00 00 > +dnl > +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=68 in_port=1 (via action) data_len=68 (unbuffered) > +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:56,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 > +00000000 50 54 00 00 00 07 40 44-44 44 54 56 81 00 20 63 > +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 > +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 > +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 > +00000040 00 00 00 00 > +]) > + > +dnl Modified MPLS controller action. > +dnl In this test, the input packet in vlan-tagged, which should be stripped > +dnl before we push the MPLS and VLAN tags. > +AT_CHECK([ovs-ofctl monitor br0 -m 65534 -P nxm --detach --pidfile 2> ofctl_monitor.log]) > + > +for i in 1 2 3; do > + ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=40:44:44:44:54:57,dst=50:54:00:00:00:07),eth_type(0x8100),vlan(vid=88,pcp=7),encap(eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no))' > +done > +OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6]) > +ovs-appctl -t ovs-ofctl exit > + > +AT_CHECK([cat ofctl_monitor.log], [0], [dnl > +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered) > +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:57,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 > +00000000 50 54 00 00 00 07 40 44-44 44 54 57 81 00 20 63 > +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 > +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 > +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 > +dnl > +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered) > +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:57,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 > +00000000 50 54 00 00 00 07 40 44-44 44 54 57 81 00 20 63 > +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 > +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 > +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 > +dnl > +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered) > +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:57,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 > +00000000 50 54 00 00 00 07 40 44-44 44 54 57 81 00 20 63 > +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 > +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 > +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 > +]) > + > +dnl Modified MPLS controller action. > +dnl In this test, the input packet in vlan-tagged, which should be stripped > +dnl before we push the MPLS and VLAN tags. > +AT_CHECK([ovs-ofctl monitor br0 65534 -m -P nxm --detach --pidfile 2> ofctl_monitor.log]) > + > +for i in 1 2 3; do > + ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=40:44:44:44:54:58,dst=50:54:00:00:00:07),eth_type(0x8100),vlan(vid=88,pcp=7),encap(eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no))' > +done > +OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6]) > +ovs-appctl -t ovs-ofctl exit > + > +AT_CHECK([cat ofctl_monitor.log], [0], [dnl > +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered) > +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:58,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 > +00000000 50 54 00 00 00 07 40 44-44 44 54 58 81 00 20 63 > +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 > +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 > +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 > +dnl > +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered) > +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:58,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 > +00000000 50 54 00 00 00 07 40 44-44 44 54 58 81 00 20 63 > +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 > +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 > +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 > +dnl > +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered) > +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:58,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 > +00000000 50 54 00 00 00 07 40 44-44 44 54 58 81 00 20 63 > +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 > +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 > +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 > +]) > + > +dnl Modified MPLS controller action. > +dnl In this test, the input packet in vlan-tagged, which should be modified > +dnl before we push MPLS and VLAN tags. > +AT_CHECK([ovs-ofctl monitor br0 65534 -m -P nxm --detach --pidfile 2> ofctl_monitor.log]) > + > +for i in 1 2 3; do > + ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=40:44:44:44:54:59,dst=50:54:00:00:00:07),eth_type(0x8100),vlan(vid=88,pcp=7),encap(eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no))' > +done > +OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6]) > +ovs-appctl -t ovs-ofctl exit > + > +AT_CHECK([cat ofctl_monitor.log], [0], [dnl > +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered) > +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:59,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 > +00000000 50 54 00 00 00 07 40 44-44 44 54 59 81 00 20 63 > +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 > +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 > +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 > +dnl > +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered) > +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:59,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 > +00000000 50 54 00 00 00 07 40 44-44 44 54 59 81 00 20 63 > +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 > +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 > +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 > +dnl > +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered) > +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:59,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 > +00000000 50 54 00 00 00 07 40 44-44 44 54 59 81 00 20 63 > +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 > +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 > +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 > +]) > + > +AT_CHECK([ovs-appctl time/warp 5000], [0], [ignore]) > +AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl > + cookie=0xa, n_packets=3, n_bytes=180, dl_src=40:44:44:44:54:50 actions=push_mpls:0x8847,load:0xa->OXM_OF_MPLS_LABEL[[]],mod_vlan_vid:99,mod_vlan_pcp:1,CONTROLLER:65535 > + cookie=0xa, n_packets=3, n_bytes=180, dl_src=40:44:44:44:54:51 actions=push_mpls:0x8847,load:0xa->OXM_OF_MPLS_LABEL[[]],mod_vlan_vid:99,mod_vlan_pcp:1,CONTROLLER:65535 > + cookie=0xa, n_packets=3, n_bytes=180, dl_src=40:44:44:44:54:52 actions=push_mpls:0x8847,load:0xa->OXM_OF_MPLS_LABEL[[]],load:0x63->OXM_OF_VLAN_VID[[]],mod_vlan_pcp:1,CONTROLLER:65535 > + cookie=0xa, n_packets=3, n_bytes=180, dl_src=40:44:44:44:54:53 actions=push_mpls:0x8847,load:0xa->OXM_OF_MPLS_LABEL[[]],load:0x63->OXM_OF_VLAN_VID[[]],mod_vlan_pcp:1,CONTROLLER:65535 > + cookie=0xa, n_packets=3, n_bytes=180, dl_src=40:44:44:44:54:54 actions=mod_vlan_vid:99,mod_vlan_pcp:1,push_mpls:0x8847,load:0xa->OXM_OF_MPLS_LABEL[[]],CONTROLLER:65535 > + cookie=0xa, n_packets=3, n_bytes=180, dl_src=40:44:44:44:54:55 actions=mod_vlan_vid:99,mod_vlan_pcp:1,push_mpls:0x8847,load:0xa->OXM_OF_MPLS_LABEL[[]],CONTROLLER:65535 > + cookie=0xa, n_packets=3, n_bytes=180, dl_src=40:44:44:44:54:56 actions=load:0x63->OXM_OF_VLAN_VID[[]],mod_vlan_pcp:1,push_mpls:0x8847,load:0xa->OXM_OF_MPLS_LABEL[[]],CONTROLLER:65535 > + cookie=0xa, n_packets=3, n_bytes=180, dl_src=40:44:44:44:54:57 actions=load:0x63->OXM_OF_VLAN_VID[[]],mod_vlan_pcp:1,push_mpls:0x8847,load:0xa->OXM_OF_MPLS_LABEL[[]],CONTROLLER:65535 > + cookie=0xa, n_packets=3, n_bytes=180, dl_src=40:44:44:44:54:58 actions=load:0x63->OXM_OF_VLAN_VID[[]],mod_vlan_pcp:1,push_mpls:0x8847,load:0xa->OXM_OF_MPLS_LABEL[[]],CONTROLLER:65535 > + cookie=0xa, n_packets=3, n_bytes=180, dl_src=40:44:44:44:54:59 actions=push_mpls:0x8847,load:0xa->OXM_OF_MPLS_LABEL[[]],mod_vlan_pcp:1,load:0x63->OXM_OF_VLAN_VID[[]],CONTROLLER:65535 > +NXST_FLOW reply: > +]) > + > +OVS_VSWITCHD_STOP > +AT_CLEANUP > + > AT_SETUP([ofproto-dpif - fragment handling]) > OVS_VSWITCHD_START > ADD_OF_PORTS([br0], [1], [2], [3], [4], [5], [6], [90]) > -- > 1.8.4 > > _______________________________________________ > dev mailing list > dev@openvswitch.org > http://openvswitch.org/mailman/listinfo/dev > -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/lib/odp-util.c b/lib/odp-util.c index 6875e01..21b33ac 100644 --- a/lib/odp-util.c +++ b/lib/odp-util.c @@ -3639,11 +3639,15 @@ commit_set_pkt_mark_action(const struct flow *flow, struct flow *base, * used as part of the action. * * Returns a reason to force processing the flow's packets into the userspace - * slow path, if there is one, otherwise 0. */ + * slow path, if there is one, otherwise 0. + * + * VLAN actions may be committed twice; If vlan_tci in 'flow' differs from the + * one in 'base', then it is committed before MPLS actions. If the VLAN_CFI + * bit of 'post_mpls_vlan_tci' is set then it is committed afterwards. */ enum slow_path_reason commit_odp_actions(const struct flow *flow, struct flow *base, struct ofpbuf *odp_actions, struct flow_wildcards *wc, - int *mpls_depth_delta) + int *mpls_depth_delta, ovs_be16 post_mpls_vlan_tci) { enum slow_path_reason slow; @@ -3656,6 +3660,10 @@ commit_odp_actions(const struct flow *flow, struct flow *base, * that it is no longer IP and thus nw and port actions are no longer valid. */ commit_mpls_action(flow, base, odp_actions, wc, mpls_depth_delta); + if (post_mpls_vlan_tci & htons(VLAN_CFI)) { + base->vlan_tci = htons(0); + commit_vlan_action(post_mpls_vlan_tci, base, odp_actions, wc); + } commit_set_priority_action(flow, base, odp_actions, wc); commit_set_pkt_mark_action(flow, base, odp_actions, wc); diff --git a/lib/odp-util.h b/lib/odp-util.h index 821b2c4..636a3ec 100644 --- a/lib/odp-util.h +++ b/lib/odp-util.h @@ -175,7 +175,8 @@ enum slow_path_reason commit_odp_actions(const struct flow *, struct flow *base, struct ofpbuf *odp_actions, struct flow_wildcards *wc, - int *mpls_depth_delta); + int *mpls_depth_delta, + ovs_be16 post_mpls_vlan_tci); /* ofproto-dpif interface. * diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c index 7be691c..d79356f 100644 --- a/ofproto/ofproto-dpif-xlate.c +++ b/ofproto/ofproto-dpif-xlate.c @@ -180,6 +180,37 @@ struct xlate_ctx { uint16_t user_cookie_offset;/* Used for user_action_cookie fixup. */ bool exit; /* No further actions should be processed. */ + /* The post MPLS vlan_tci. + * + * The value of the vlan TCI prior to the translation of an MPLS push + * actions should be stored in 'xin->flow->vlan_tci'. + * + * If an VLAN or set field action is subsequently translated then + * 'post_mpls_vlan_tci' is updated as according to the action. + * + * If the VLAN_CFI bit of 'post_mpls_vlan_tci' is set then VLAN ODP actions + * will be committed after any MPLS actions regardless of whether VLAN + * actions were also committed before the MPLS actions or not. + * + * This mechanism allows a VLAN tag to be popped before pushing + * an MPLS LSE and then the same VLAN tag pushed after pushing + * the MPLS LSE. In this way it is possible to push an MPLS LSE + * after an existing VLAN tag. Moreover this mechanism allows + * the order in which VLAN tags and MPLS LSEs are pushed. */ + ovs_be16 post_mpls_vlan_tci; + + /* The next vlan_tci state. + * + * This field pints to the variable update each time an + * action updates the VLAN tci. + * + * This variable initially points to 'xin->flow->vlan_tci' so that ODP + * VLAN actions are committed before any MPLS actions. When an MPLS + * action is composed 'next_vlan_tci' is updated to point to + * 'post_mpls_vlan_tci'. This causes subsequent VLAN actions to be + * committed after MPLS actions. */ + ovs_be16 *next_vlan_tci; + /* OpenFlow 1.1+ action set. * * 'action_set' accumulates "struct ofpact"s added by OFPACT_WRITE_ACTIONS. @@ -996,11 +1027,38 @@ output_vlan_to_vid(const struct xbundle *out_xbundle, uint16_t vlan) } } +static bool mpls_actions_xlated(struct xlate_ctx *ctx) +{ + return ctx->next_vlan_tci == &ctx->post_mpls_vlan_tci; +} + +static ovs_be16 +vlan_tci_save(struct xlate_ctx *ctx) +{ + ovs_be16 orig_tci = ctx->xin->flow.vlan_tci; + /* If MPLS actions were executed after vlan actions then + * copy the final vlan_tci out and restore the intermediate VLAN state. */ + if (mpls_actions_xlated(ctx)) { + ctx->xin->flow.vlan_tci = *ctx->next_vlan_tci; + } + return orig_tci; +} + +static void +vlan_tci_restore(struct xlate_ctx *ctx, ovs_be16 orig_tci) +{ + /* If MPLS actions were executed after vlan actions then + * copy the final vlan_tci out and restore the intermediate VLAN state. */ + if (mpls_actions_xlated(ctx)) { + ctx->post_mpls_vlan_tci = ctx->xin->flow.vlan_tci; + ctx->xin->flow.vlan_tci = orig_tci; + } +} + static void output_normal(struct xlate_ctx *ctx, const struct xbundle *out_xbundle, uint16_t vlan) { - ovs_be16 *flow_tci = &ctx->xin->flow.vlan_tci; uint16_t vid; ovs_be16 tci, old_tci; struct xport *xport; @@ -1025,18 +1083,18 @@ output_normal(struct xlate_ctx *ctx, const struct xbundle *out_xbundle, } } - old_tci = *flow_tci; + old_tci = *ctx->next_vlan_tci; tci = htons(vid); if (tci || out_xbundle->use_priority_tags) { - tci |= *flow_tci & htons(VLAN_PCP_MASK); + tci |= *ctx->next_vlan_tci & htons(VLAN_PCP_MASK); if (tci) { tci |= htons(VLAN_CFI); } } - *flow_tci = tci; + ctx->xin->flow.vlan_tci = *ctx->next_vlan_tci = tci; compose_output_action(ctx, xport->ofp_port); - *flow_tci = old_tci; + ctx->xin->flow.vlan_tci = *ctx->next_vlan_tci = old_tci; } /* A VM broadcasts a gratuitous ARP to indicate that it has resumed after @@ -1269,7 +1327,7 @@ xlate_normal(struct xlate_ctx *ctx) /* Drop malformed frames. */ if (flow->dl_type == htons(ETH_TYPE_VLAN) && - !(flow->vlan_tci & htons(VLAN_CFI))) { + !(*ctx->next_vlan_tci & htons(VLAN_CFI))) { if (ctx->xin->packet != NULL) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); VLOG_WARN_RL(&rl, "bridge %s: dropping packet with partial " @@ -1293,7 +1351,7 @@ xlate_normal(struct xlate_ctx *ctx) } /* Check VLAN. */ - vid = vlan_tci_to_vid(flow->vlan_tci); + vid = vlan_tci_to_vid(*ctx->next_vlan_tci); if (!input_vid_is_valid(vid, in_xbundle, ctx->xin->packet != NULL)) { xlate_report(ctx, "disallowed VLAN VID for this input port, dropping"); return; @@ -1551,7 +1609,7 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port, const struct xport *xport = get_ofp_port(ctx->xbridge, ofp_port); struct flow_wildcards *wc = &ctx->xout->wc; struct flow *flow = &ctx->xin->flow; - ovs_be16 flow_vlan_tci; + ovs_be16 flow_vlan_tci, vlan_tci; uint32_t flow_pkt_mark; uint8_t flow_nw_tos; odp_port_t out_port, odp_port; @@ -1620,6 +1678,7 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port, } flow_vlan_tci = flow->vlan_tci; + vlan_tci = *ctx->next_vlan_tci; flow_pkt_mark = flow->pkt_mark; flow_nw_tos = flow->nw_tos; @@ -1659,12 +1718,13 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port, wc->masks.vlan_tci |= htons(VLAN_VID_MASK | VLAN_CFI); } vlandev_port = vsp_realdev_to_vlandev(ctx->xbridge->ofproto, ofp_port, - flow->vlan_tci); + *ctx->next_vlan_tci); if (vlandev_port == ofp_port) { out_port = odp_port; } else { out_port = ofp_port_to_odp_port(ctx->xbridge, vlandev_port); flow->vlan_tci = htons(0); + ctx->post_mpls_vlan_tci = htons(0); } } @@ -1672,7 +1732,8 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port, ctx->xout->slow |= commit_odp_actions(flow, &ctx->base_flow, &ctx->xout->odp_actions, &ctx->xout->wc, - &ctx->mpls_depth_delta); + &ctx->mpls_depth_delta, + ctx->post_mpls_vlan_tci); nl_msg_put_odp_port(&ctx->xout->odp_actions, OVS_ACTION_ATTR_OUTPUT, out_port); @@ -1684,6 +1745,7 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port, out: /* Restore flow */ flow->vlan_tci = flow_vlan_tci; + *ctx->next_vlan_tci = vlan_tci; flow->pkt_mark = flow_pkt_mark; flow->nw_tos = flow_nw_tos; } @@ -1838,7 +1900,8 @@ execute_controller_action(struct xlate_ctx *ctx, int len, ctx->xout->slow |= commit_odp_actions(&ctx->xin->flow, &ctx->base_flow, &ctx->xout->odp_actions, &ctx->xout->wc, - &ctx->mpls_depth_delta); + &ctx->mpls_depth_delta, + ctx->post_mpls_vlan_tci); odp_execute_actions(NULL, packet, &key, ctx->xout->odp_actions.data, ctx->xout->odp_actions.size, NULL, NULL); @@ -2231,7 +2294,8 @@ xlate_sample_action(struct xlate_ctx *ctx, ctx->xout->slow |= commit_odp_actions(&ctx->xin->flow, &ctx->base_flow, &ctx->xout->odp_actions, &ctx->xout->wc, - &ctx->mpls_depth_delta); + &ctx->mpls_depth_delta, + ctx->post_mpls_vlan_tci); compose_flow_sample_cookie(os->probability, os->collector_set_id, os->obs_domain_id, os->obs_point_id, &cookie); @@ -2320,28 +2384,28 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, case OFPACT_SET_VLAN_VID: wc->masks.vlan_tci |= htons(VLAN_VID_MASK | VLAN_CFI); - flow->vlan_tci &= ~htons(VLAN_VID_MASK); - flow->vlan_tci |= (htons(ofpact_get_SET_VLAN_VID(a)->vlan_vid) - | htons(VLAN_CFI)); + *ctx->next_vlan_tci &= ~htons(VLAN_VID_MASK); + *ctx->next_vlan_tci |= (htons(ofpact_get_SET_VLAN_VID(a)->vlan_vid) + | htons(VLAN_CFI)); break; case OFPACT_SET_VLAN_PCP: wc->masks.vlan_tci |= htons(VLAN_PCP_MASK | VLAN_CFI); - flow->vlan_tci &= ~htons(VLAN_PCP_MASK); - flow->vlan_tci |= + *ctx->next_vlan_tci &= ~htons(VLAN_PCP_MASK); + *ctx->next_vlan_tci |= htons((ofpact_get_SET_VLAN_PCP(a)->vlan_pcp << VLAN_PCP_SHIFT) | VLAN_CFI); break; case OFPACT_STRIP_VLAN: memset(&wc->masks.vlan_tci, 0xff, sizeof wc->masks.vlan_tci); - flow->vlan_tci = htons(0); + *ctx->next_vlan_tci = htons(0); break; case OFPACT_PUSH_VLAN: /* XXX 802.1AD(QinQ) */ memset(&wc->masks.vlan_tci, 0xff, sizeof wc->masks.vlan_tci); - flow->vlan_tci = htons(VLAN_CFI); + *ctx->next_vlan_tci = htons(VLAN_CFI); break; case OFPACT_SET_ETH_SRC: @@ -2423,29 +2487,53 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, flow->skb_priority = ctx->orig_skb_priority; break; - case OFPACT_REG_MOVE: + case OFPACT_REG_MOVE: { + ovs_be16 orig_tci = flow->vlan_tci; nxm_execute_reg_move(ofpact_get_REG_MOVE(a), flow, wc); + vlan_tci_restore(ctx, orig_tci); break; + } - case OFPACT_REG_LOAD: + case OFPACT_REG_LOAD: { + ovs_be16 orig_tci = vlan_tci_save(ctx); nxm_execute_reg_load(ofpact_get_REG_LOAD(a), flow, wc); + vlan_tci_restore(ctx, orig_tci); break; + } - case OFPACT_STACK_PUSH: + case OFPACT_STACK_PUSH: { + ovs_be16 orig_tci = vlan_tci_save(ctx); nxm_execute_stack_push(ofpact_get_STACK_PUSH(a), flow, wc, &ctx->stack); + vlan_tci_restore(ctx, orig_tci); break; + } - case OFPACT_STACK_POP: + case OFPACT_STACK_POP: { + ovs_be16 orig_tci = vlan_tci_save(ctx); nxm_execute_stack_pop(ofpact_get_STACK_POP(a), flow, wc, &ctx->stack); + vlan_tci_restore(ctx, orig_tci); break; + } case OFPACT_PUSH_MPLS: if (compose_mpls_push_action(ctx, ofpact_get_PUSH_MPLS(a)->ethertype)) { return; } + + /* Save and pop any existing VLAN tags. They will be pushed + * back onto the packet after pushing the MPLS LSE. The overall + * effect is to push the MPLS LSE after any VLAN tags that may + * be present. This is the behaviour described for OpenFlow 1.1 + * and 1.2. This code needs to be enhanced to make this + * conditional to also and support pushing the MPLS LSE before + * any VLAN tags that may be present, the behaviour described + * for OpenFlow 1.3. */ + ctx->post_mpls_vlan_tci = *ctx->next_vlan_tci; + flow->vlan_tci = htons(0); + ctx->next_vlan_tci = &ctx->post_mpls_vlan_tci; break; case OFPACT_POP_MPLS: @@ -2786,6 +2874,8 @@ xlate_actions__(struct xlate_in *xin, struct xlate_out *xout) ctx.table_id = 0; ctx.exit = false; ctx.mpls_depth_delta = 0; + ctx.post_mpls_vlan_tci = htons(0); + ctx.next_vlan_tci = &ctx.xin->flow.vlan_tci; if (!xin->ofpacts && !ctx.rule) { rule_dpif_lookup(ctx.xbridge->ofproto, flow, wc, &rule); diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at index c569463..372bce7 100644 --- a/tests/ofproto-dpif.at +++ b/tests/ofproto-dpif.at @@ -965,6 +965,395 @@ done OVS_VSWITCHD_STOP AT_CLEANUP +AT_SETUP([ofproto-dpif - OF1.2 VLAN+MPLS handling]) +OVS_VSWITCHD_START([dnl + add-port br0 p1 -- set Interface p1 type=dummy +]) +ON_EXIT([kill `cat ovs-ofctl.pid`]) + +AT_CAPTURE_FILE([ofctl_monitor.log]) +AT_DATA([flows.txt], [dnl +cookie=0xa dl_src=40:44:44:44:54:50 actions=push_mpls:0x8847,load:10->OXM_OF_MPLS_LABEL[[]],push_vlan:0x8100,mod_vlan_vid:99,mod_vlan_pcp:1,controller +cookie=0xa dl_src=40:44:44:44:54:51 actions=push_mpls:0x8847,load:10->OXM_OF_MPLS_LABEL[[]],push_vlan:0x8100,mod_vlan_vid:99,mod_vlan_pcp:1,controller +cookie=0xa dl_src=40:44:44:44:54:52 actions=push_mpls:0x8847,load:10->OXM_OF_MPLS_LABEL[[]],push_vlan:0x8100,load:99->OXM_OF_VLAN_VID[[]],mod_vlan_pcp:1,controller +cookie=0xa dl_src=40:44:44:44:54:53 actions=push_mpls:0x8847,load:10->OXM_OF_MPLS_LABEL[[]],push_vlan:0x8100,load:99->OXM_OF_VLAN_VID[[]],mod_vlan_pcp:1,controller +cookie=0xa dl_src=40:44:44:44:54:54 actions=push_vlan:0x8100,mod_vlan_vid:99,mod_vlan_pcp:1,push_mpls:0x8847,load:10->OXM_OF_MPLS_LABEL[[]],controller +cookie=0xa dl_src=40:44:44:44:54:55 actions=push_vlan:0x8100,mod_vlan_vid:99,mod_vlan_pcp:1,push_mpls:0x8847,load:10->OXM_OF_MPLS_LABEL[[]],controller +cookie=0xa dl_src=40:44:44:44:54:56 actions=push_vlan:0x8100,load:99->OXM_OF_VLAN_VID[[]],mod_vlan_pcp:1,push_mpls:0x8847,load:10->OXM_OF_MPLS_LABEL[[]],controller +cookie=0xa dl_src=40:44:44:44:54:57 actions=push_vlan:0x8100,load:99->OXM_OF_VLAN_VID[[]],mod_vlan_pcp:1,push_mpls:0x8847,load:10->OXM_OF_MPLS_LABEL[[]],controller +cookie=0xa dl_src=40:44:44:44:54:58 actions=load:99->OXM_OF_VLAN_VID[[]],mod_vlan_pcp:1,push_mpls:0x8847,load:10->OXM_OF_MPLS_LABEL[[]],controller +cookie=0xa dl_src=40:44:44:44:54:59 actions=push_mpls:0x8847,load:10->OXM_OF_MPLS_LABEL[[]],mod_vlan_pcp:1,load:99->OXM_OF_VLAN_VID[[]],controller +]) +AT_CHECK([ovs-ofctl --protocols=OpenFlow12 add-flows br0 flows.txt]) + +dnl Modified MPLS controller action. +dnl In this test, we push the MPLS tag before pushing a VLAN tag, so we see +dnl both of these in the final flow +AT_CHECK([ovs-ofctl monitor br0 65534 -m -P nxm --detach --pidfile 2> ofctl_monitor.log]) + +for i in 1 2 3; do + ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=40:44:44:44:54:50,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no)' +done +OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit]) + +AT_CHECK([cat ofctl_monitor.log], [0], [dnl +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=68 in_port=1 (via action) data_len=68 (unbuffered) +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:50,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 +00000000 50 54 00 00 00 07 40 44-44 44 54 50 81 00 20 63 +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 +00000040 00 00 00 00 +dnl +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=68 in_port=1 (via action) data_len=68 (unbuffered) +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:50,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 +00000000 50 54 00 00 00 07 40 44-44 44 54 50 81 00 20 63 +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 +00000040 00 00 00 00 +dnl +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=68 in_port=1 (via action) data_len=68 (unbuffered) +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:50,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 +00000000 50 54 00 00 00 07 40 44-44 44 54 50 81 00 20 63 +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 +00000040 00 00 00 00 +]) + +dnl Modified MPLS controller action. +dnl In this test, the input packet in vlan-tagged, which should be stripped +dnl before we push the MPLS and VLAN tags. +AT_CHECK([ovs-ofctl monitor br0 65534 -m -P nxm --detach --pidfile 2> ofctl_monitor.log]) + +for i in 1 2 3; do + ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=40:44:44:44:54:51,dst=50:54:00:00:00:07),eth_type(0x8100),vlan(vid=88,pcp=7),encap(eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no))' +done +OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6]) +ovs-appctl -t ovs-ofctl exit + +AT_CHECK([cat ofctl_monitor.log], [0], [dnl +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered) +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:51,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 +00000000 50 54 00 00 00 07 40 44-44 44 54 51 81 00 20 63 +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 +dnl +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered) +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:51,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 +00000000 50 54 00 00 00 07 40 44-44 44 54 51 81 00 20 63 +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 +dnl +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered) +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:51,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 +00000000 50 54 00 00 00 07 40 44-44 44 54 51 81 00 20 63 +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 +]) + +dnl Modified MPLS controller action. +dnl In this test, we push the MPLS tag before pushing a VLAN tag, so we see +dnl both of these in the final flow +AT_CHECK([ovs-ofctl monitor br0 65534 -m -P nxm --detach --pidfile 2> ofctl_monitor.log]) + +for i in 1 2 3; do + ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=40:44:44:44:54:52,dst=52:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no)' +done +OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit]) + +AT_CHECK([cat ofctl_monitor.log], [0], [dnl +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=68 in_port=1 (via action) data_len=68 (unbuffered) +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:52,dl_dst=52:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 +00000000 52 54 00 00 00 07 40 44-44 44 54 52 81 00 20 63 +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 +00000040 00 00 00 00 +dnl +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=68 in_port=1 (via action) data_len=68 (unbuffered) +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:52,dl_dst=52:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 +00000000 52 54 00 00 00 07 40 44-44 44 54 52 81 00 20 63 +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 +00000040 00 00 00 00 +dnl +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=68 in_port=1 (via action) data_len=68 (unbuffered) +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:52,dl_dst=52:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 +00000000 52 54 00 00 00 07 40 44-44 44 54 52 81 00 20 63 +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 +00000040 00 00 00 00 +]) + +dnl Modified MPLS controller action. +dnl In this test, the input packet in vlan-tagged, which should be stripped +dnl before we push the MPLS and VLAN tags. +AT_CHECK([ovs-ofctl monitor br0 65534 -m -P nxm --detach --pidfile 2> ofctl_monitor.log]) + +for i in 1 2 3; do + ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=40:44:44:44:54:53,dst=50:54:00:00:00:07),eth_type(0x8100),vlan(vid=88,pcp=7),encap(eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no))' +done +OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6]) +ovs-appctl -t ovs-ofctl exit + +AT_CHECK([cat ofctl_monitor.log], [0], [dnl +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered) +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:53,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 +00000000 50 54 00 00 00 07 40 44-44 44 54 53 81 00 20 63 +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 +dnl +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered) +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:53,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 +00000000 50 54 00 00 00 07 40 44-44 44 54 53 81 00 20 63 +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 +dnl +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered) +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:53,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 +00000000 50 54 00 00 00 07 40 44-44 44 54 53 81 00 20 63 +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 +]) + +dnl Modified MPLS controller action. +dnl In this test, we push the VLAN tag before pushing a MPLS tag, but these +dnl actions are reordered, so we see both of these in the final flow. +AT_CHECK([ovs-ofctl monitor br0 65534 -m -P nxm --detach --pidfile 2> ofctl_monitor.log]) + +for i in 1 2 3; do + ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=40:44:44:44:54:54,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no)' +done +OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6]) +ovs-appctl -t ovs-ofctl exit + +AT_CHECK([cat ofctl_monitor.log], [0], [dnl +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=68 in_port=1 (via action) data_len=68 (unbuffered) +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:54,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 +00000000 50 54 00 00 00 07 40 44-44 44 54 54 81 00 20 63 +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 +00000040 00 00 00 00 +dnl +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=68 in_port=1 (via action) data_len=68 (unbuffered) +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:54,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 +00000000 50 54 00 00 00 07 40 44-44 44 54 54 81 00 20 63 +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 +00000040 00 00 00 00 +dnl +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=68 in_port=1 (via action) data_len=68 (unbuffered) +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:54,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 +00000000 50 54 00 00 00 07 40 44-44 44 54 54 81 00 20 63 +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 +00000040 00 00 00 00 +]) + +dnl Modified MPLS controller action. +dnl In this test, the input packet in vlan-tagged, which should be stripped +dnl before we push the MPLS and VLAN tags. +AT_CHECK([ovs-ofctl monitor br0 65534 -m -P nxm --detach --pidfile 2> ofctl_monitor.log]) + +for i in 1 2 3; do + ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=40:44:44:44:54:55,dst=50:54:00:00:00:07),eth_type(0x8100),vlan(vid=88,pcp=7),encap(eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no))' +done +OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6]) +ovs-appctl -t ovs-ofctl exit + +AT_CHECK([cat ofctl_monitor.log], [0], [dnl +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered) +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:55,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 +00000000 50 54 00 00 00 07 40 44-44 44 54 55 81 00 20 63 +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 +dnl +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered) +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:55,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 +00000000 50 54 00 00 00 07 40 44-44 44 54 55 81 00 20 63 +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 +dnl +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered) +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:55,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 +00000000 50 54 00 00 00 07 40 44-44 44 54 55 81 00 20 63 +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 +]) + +dnl Modified MPLS controller action. +dnl In this test, we push the VLAN tag before pushing a MPLS tag, but these +dnl actions are reordered, so we see both of these in the final flow. +AT_CHECK([ovs-ofctl monitor br0 65534 -m -P nxm --detach --pidfile 2> ofctl_monitor.log]) + +for i in 1 2 3; do + ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=40:44:44:44:54:56,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no)' +done +OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6]) +ovs-appctl -t ovs-ofctl exit + +AT_CHECK([cat ofctl_monitor.log], [0], [dnl +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=68 in_port=1 (via action) data_len=68 (unbuffered) +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:56,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 +00000000 50 54 00 00 00 07 40 44-44 44 54 56 81 00 20 63 +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 +00000040 00 00 00 00 +dnl +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=68 in_port=1 (via action) data_len=68 (unbuffered) +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:56,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 +00000000 50 54 00 00 00 07 40 44-44 44 54 56 81 00 20 63 +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 +00000040 00 00 00 00 +dnl +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=68 in_port=1 (via action) data_len=68 (unbuffered) +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:56,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 +00000000 50 54 00 00 00 07 40 44-44 44 54 56 81 00 20 63 +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 +00000040 00 00 00 00 +]) + +dnl Modified MPLS controller action. +dnl In this test, the input packet in vlan-tagged, which should be stripped +dnl before we push the MPLS and VLAN tags. +AT_CHECK([ovs-ofctl monitor br0 -m 65534 -P nxm --detach --pidfile 2> ofctl_monitor.log]) + +for i in 1 2 3; do + ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=40:44:44:44:54:57,dst=50:54:00:00:00:07),eth_type(0x8100),vlan(vid=88,pcp=7),encap(eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no))' +done +OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6]) +ovs-appctl -t ovs-ofctl exit + +AT_CHECK([cat ofctl_monitor.log], [0], [dnl +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered) +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:57,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 +00000000 50 54 00 00 00 07 40 44-44 44 54 57 81 00 20 63 +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 +dnl +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered) +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:57,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 +00000000 50 54 00 00 00 07 40 44-44 44 54 57 81 00 20 63 +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 +dnl +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered) +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:57,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 +00000000 50 54 00 00 00 07 40 44-44 44 54 57 81 00 20 63 +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 +]) + +dnl Modified MPLS controller action. +dnl In this test, the input packet in vlan-tagged, which should be stripped +dnl before we push the MPLS and VLAN tags. +AT_CHECK([ovs-ofctl monitor br0 65534 -m -P nxm --detach --pidfile 2> ofctl_monitor.log]) + +for i in 1 2 3; do + ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=40:44:44:44:54:58,dst=50:54:00:00:00:07),eth_type(0x8100),vlan(vid=88,pcp=7),encap(eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no))' +done +OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6]) +ovs-appctl -t ovs-ofctl exit + +AT_CHECK([cat ofctl_monitor.log], [0], [dnl +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered) +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:58,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 +00000000 50 54 00 00 00 07 40 44-44 44 54 58 81 00 20 63 +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 +dnl +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered) +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:58,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 +00000000 50 54 00 00 00 07 40 44-44 44 54 58 81 00 20 63 +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 +dnl +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered) +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:58,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 +00000000 50 54 00 00 00 07 40 44-44 44 54 58 81 00 20 63 +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 +]) + +dnl Modified MPLS controller action. +dnl In this test, the input packet in vlan-tagged, which should be modified +dnl before we push MPLS and VLAN tags. +AT_CHECK([ovs-ofctl monitor br0 65534 -m -P nxm --detach --pidfile 2> ofctl_monitor.log]) + +for i in 1 2 3; do + ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=40:44:44:44:54:59,dst=50:54:00:00:00:07),eth_type(0x8100),vlan(vid=88,pcp=7),encap(eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no))' +done +OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6]) +ovs-appctl -t ovs-ofctl exit + +AT_CHECK([cat ofctl_monitor.log], [0], [dnl +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered) +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:59,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 +00000000 50 54 00 00 00 07 40 44-44 44 54 59 81 00 20 63 +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 +dnl +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered) +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:59,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 +00000000 50 54 00 00 00 07 40 44-44 44 54 59 81 00 20 63 +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 +dnl +NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered) +mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:54:59,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=0,mpls_ttl=64,mpls_bos=1 +00000000 50 54 00 00 00 07 40 44-44 44 54 59 81 00 20 63 +00000010 88 47 00 00 a1 40 45 00-00 28 00 00 00 00 40 06 +00000020 f9 7c c0 a8 00 01 c0 a8-00 02 00 00 00 00 00 00 +00000030 00 00 00 00 00 00 50 00-00 00 00 00 00 00 00 00 +]) + +AT_CHECK([ovs-appctl time/warp 5000], [0], [ignore]) +AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl + cookie=0xa, n_packets=3, n_bytes=180, dl_src=40:44:44:44:54:50 actions=push_mpls:0x8847,load:0xa->OXM_OF_MPLS_LABEL[[]],mod_vlan_vid:99,mod_vlan_pcp:1,CONTROLLER:65535 + cookie=0xa, n_packets=3, n_bytes=180, dl_src=40:44:44:44:54:51 actions=push_mpls:0x8847,load:0xa->OXM_OF_MPLS_LABEL[[]],mod_vlan_vid:99,mod_vlan_pcp:1,CONTROLLER:65535 + cookie=0xa, n_packets=3, n_bytes=180, dl_src=40:44:44:44:54:52 actions=push_mpls:0x8847,load:0xa->OXM_OF_MPLS_LABEL[[]],load:0x63->OXM_OF_VLAN_VID[[]],mod_vlan_pcp:1,CONTROLLER:65535 + cookie=0xa, n_packets=3, n_bytes=180, dl_src=40:44:44:44:54:53 actions=push_mpls:0x8847,load:0xa->OXM_OF_MPLS_LABEL[[]],load:0x63->OXM_OF_VLAN_VID[[]],mod_vlan_pcp:1,CONTROLLER:65535 + cookie=0xa, n_packets=3, n_bytes=180, dl_src=40:44:44:44:54:54 actions=mod_vlan_vid:99,mod_vlan_pcp:1,push_mpls:0x8847,load:0xa->OXM_OF_MPLS_LABEL[[]],CONTROLLER:65535 + cookie=0xa, n_packets=3, n_bytes=180, dl_src=40:44:44:44:54:55 actions=mod_vlan_vid:99,mod_vlan_pcp:1,push_mpls:0x8847,load:0xa->OXM_OF_MPLS_LABEL[[]],CONTROLLER:65535 + cookie=0xa, n_packets=3, n_bytes=180, dl_src=40:44:44:44:54:56 actions=load:0x63->OXM_OF_VLAN_VID[[]],mod_vlan_pcp:1,push_mpls:0x8847,load:0xa->OXM_OF_MPLS_LABEL[[]],CONTROLLER:65535 + cookie=0xa, n_packets=3, n_bytes=180, dl_src=40:44:44:44:54:57 actions=load:0x63->OXM_OF_VLAN_VID[[]],mod_vlan_pcp:1,push_mpls:0x8847,load:0xa->OXM_OF_MPLS_LABEL[[]],CONTROLLER:65535 + cookie=0xa, n_packets=3, n_bytes=180, dl_src=40:44:44:44:54:58 actions=load:0x63->OXM_OF_VLAN_VID[[]],mod_vlan_pcp:1,push_mpls:0x8847,load:0xa->OXM_OF_MPLS_LABEL[[]],CONTROLLER:65535 + cookie=0xa, n_packets=3, n_bytes=180, dl_src=40:44:44:44:54:59 actions=push_mpls:0x8847,load:0xa->OXM_OF_MPLS_LABEL[[]],mod_vlan_pcp:1,load:0x63->OXM_OF_VLAN_VID[[]],CONTROLLER:65535 +NXST_FLOW reply: +]) + +OVS_VSWITCHD_STOP +AT_CLEANUP + AT_SETUP([ofproto-dpif - fragment handling]) OVS_VSWITCHD_START ADD_OF_PORTS([br0], [1], [2], [3], [4], [5], [6], [90])