diff options
-rw-r--r-- | NEWS | 1 | ||||
-rw-r--r-- | include/openvswitch/ofp-actions.h | 1 | ||||
-rw-r--r-- | lib/ofp-actions.c | 49 | ||||
-rw-r--r-- | ofproto/ofproto-dpif-xlate.c | 31 | ||||
-rw-r--r-- | tests/nsh.at | 6 | ||||
-rw-r--r-- | utilities/ovs-ofctl.8.in | 13 |
6 files changed, 97 insertions, 4 deletions
@@ -2,6 +2,7 @@ Post-v2.8.0 -------------------- - NSH implementation now conforms to latest draft (draft-ietf-sfc-nsh-28). * Add ttl field. + * Add a new action dec_nsh_ttl. - OVSDB: * New high-level documentation in ovsdb(7). * New file format documentation for developers in ovsdb(5). diff --git a/include/openvswitch/ofp-actions.h b/include/openvswitch/ofp-actions.h index a7808eb4f..4e957358f 100644 --- a/include/openvswitch/ofp-actions.h +++ b/include/openvswitch/ofp-actions.h @@ -93,6 +93,7 @@ struct vl_mff_map; OFPACT(DEC_MPLS_TTL, ofpact_null, ofpact, "dec_mpls_ttl") \ OFPACT(PUSH_MPLS, ofpact_push_mpls, ofpact, "push_mpls") \ OFPACT(POP_MPLS, ofpact_pop_mpls, ofpact, "pop_mpls") \ + OFPACT(DEC_NSH_TTL, ofpact_null, ofpact, "dec_nsh_ttl") \ \ /* Generic encap & decap */ \ OFPACT(ENCAP, ofpact_encap, props, "encap") \ diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c index 1d364f98b..db933634b 100644 --- a/lib/ofp-actions.c +++ b/lib/ofp-actions.c @@ -350,6 +350,9 @@ enum ofp_raw_action_type { /* NX1.3+(47): struct nx_action_decap, ... */ NXAST_RAW_DECAP, + /* NX1.3+(48): void. */ + NXAST_RAW_DEC_NSH_TTL, + /* ## ------------------ ## */ /* ## Debugging actions. ## */ /* ## ------------------ ## */ @@ -486,6 +489,7 @@ ofpact_next_flattened(const struct ofpact *ofpact) case OFPACT_NAT: case OFPACT_ENCAP: case OFPACT_DECAP: + case OFPACT_DEC_NSH_TTL: return ofpact_next(ofpact); case OFPACT_CLONE: @@ -4336,6 +4340,39 @@ format_DECAP(const struct ofpact_decap *a, ds_put_format(s, "%s)%s", colors.paren, colors.end); } +/* Action dec_nsh_ttl */ + +static enum ofperr +decode_NXAST_RAW_DEC_NSH_TTL(struct ofpbuf *out) +{ + ofpact_put_DEC_NSH_TTL(out); + return 0; +} + +static void +encode_DEC_NSH_TTL(const struct ofpact_null *null OVS_UNUSED, + enum ofp_version ofp_version OVS_UNUSED, struct ofpbuf *out) +{ + put_NXAST_DEC_NSH_TTL(out); +} + +static char * OVS_WARN_UNUSED_RESULT +parse_DEC_NSH_TTL(char *arg OVS_UNUSED, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ofpbuf *ofpacts, + enum ofputil_protocol *usable_protocols OVS_UNUSED) +{ + ofpact_put_DEC_NSH_TTL(ofpacts); + return NULL; +} + +static void +format_DEC_NSH_TTL(const struct ofpact_null *a OVS_UNUSED, + const struct ofputil_port_map *port_map OVS_UNUSED, struct ds *s) +{ + ds_put_format(s, "%sdec_nsh_ttl%s", colors.special, colors.end); +} + /* Action structures for NXAST_RESUBMIT, NXAST_RESUBMIT_TABLE, and * NXAST_RESUBMIT_TABLE_CT. @@ -7156,6 +7193,7 @@ ofpact_is_set_or_move_action(const struct ofpact *a) case OFPACT_SET_VLAN_VID: case OFPACT_ENCAP: case OFPACT_DECAP: + case OFPACT_DEC_NSH_TTL: return true; case OFPACT_BUNDLE: case OFPACT_CLEAR_ACTIONS: @@ -7234,6 +7272,7 @@ ofpact_is_allowed_in_actions_set(const struct ofpact *a) case OFPACT_STRIP_VLAN: case OFPACT_ENCAP: case OFPACT_DECAP: + case OFPACT_DEC_NSH_TTL: return true; /* In general these actions are excluded because they are not part of @@ -7348,6 +7387,7 @@ ofpacts_execute_action_set(struct ofpbuf *action_list, ofpacts_copy_last(action_list, action_set, OFPACT_PUSH_VLAN); ofpacts_copy_last(action_list, action_set, OFPACT_DEC_TTL); ofpacts_copy_last(action_list, action_set, OFPACT_DEC_MPLS_TTL); + ofpacts_copy_last(action_list, action_set, OFPACT_DEC_NSH_TTL); ofpacts_copy_all(action_list, action_set, ofpact_is_set_or_move_action); ofpacts_copy_last(action_list, action_set, OFPACT_SET_QUEUE); @@ -7490,6 +7530,7 @@ ovs_instruction_type_from_ofpact_type(enum ofpact_type type) case OFPACT_NAT: case OFPACT_ENCAP: case OFPACT_DECAP: + case OFPACT_DEC_NSH_TTL: default: return OVSINST_OFPIT11_APPLY_ACTIONS; } @@ -8177,6 +8218,13 @@ ofpact_check__(enum ofputil_protocol *usable_protocols, struct ofpact *a, } return 0; + case OFPACT_DEC_NSH_TTL: + if ((flow->packet_type != htonl(PT_NSH)) && + (flow->dl_type != htons(ETH_TYPE_NSH))) { + inconsistent_match(usable_protocols); + } + return 0; + default: OVS_NOT_REACHED(); } @@ -8673,6 +8721,7 @@ ofpact_outputs_to_port(const struct ofpact *ofpact, ofp_port_t port) case OFPACT_NAT: case OFPACT_ENCAP: case OFPACT_DECAP: + case OFPACT_DEC_NSH_TTL: default: return false; } diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c index effa9c23d..896d5e290 100644 --- a/ofproto/ofproto-dpif-xlate.c +++ b/ofproto/ofproto-dpif-xlate.c @@ -4647,6 +4647,28 @@ compose_set_mpls_tc_action(struct xlate_ctx *ctx, uint8_t tc) } } +static bool +compose_dec_nsh_ttl_action(struct xlate_ctx *ctx) +{ + struct flow *flow = &ctx->xin->flow; + + if ((flow->packet_type == htonl(PT_NSH)) || + (flow->dl_type == htons(ETH_TYPE_NSH))) { + ctx->wc->masks.nsh.ttl = 0xff; + if (flow->nsh.ttl > 1) { + flow->nsh.ttl--; + return false; + } else { + xlate_controller_action(ctx, UINT16_MAX, OFPR_INVALID_TTL, + 0, NULL, 0); + } + } + + /* Stop processing for current table. */ + xlate_report(ctx, OFT_WARN, "NSH decrement TTL exception"); + return true; +} + static void compose_set_mpls_ttl_action(struct xlate_ctx *ctx, uint8_t ttl) { @@ -5196,6 +5218,7 @@ reversible_actions(const struct ofpact *ofpacts, size_t ofpacts_len) case OFPACT_OUTPUT_TRUNC: case OFPACT_ENCAP: case OFPACT_DECAP: + case OFPACT_DEC_NSH_TTL: return false; } } @@ -5423,6 +5446,7 @@ freeze_unroll_actions(const struct ofpact *a, const struct ofpact *end, case OFPACT_OUTPUT: case OFPACT_CONTROLLER: case OFPACT_DEC_MPLS_TTL: + case OFPACT_DEC_NSH_TTL: case OFPACT_DEC_TTL: /* These actions may generate asynchronous messages, which include * table ID and flow cookie information. */ @@ -5971,6 +5995,7 @@ recirc_for_mpls(const struct ofpact *a, struct xlate_ctx *ctx) case OFPACT_CLONE: case OFPACT_ENCAP: case OFPACT_DECAP: + case OFPACT_DEC_NSH_TTL: case OFPACT_UNROLL_XLATE: case OFPACT_CT: case OFPACT_CT_CLEAR: @@ -6295,6 +6320,12 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, } break; + case OFPACT_DEC_NSH_TTL: + if (compose_dec_nsh_ttl_action(ctx)) { + return; + } + break; + case OFPACT_DEC_TTL: wc->masks.nw_ttl = 0xff; if (compose_dec_ttl(ctx, ofpact_get_DEC_TTL(a))) { diff --git a/tests/nsh.at b/tests/nsh.at index 6177cea8b..e6a834518 100644 --- a/tests/nsh.at +++ b/tests/nsh.at @@ -542,7 +542,7 @@ AT_DATA([br-in2.txt], [dnl table=2,packet_type=(1,0x894f),nsh_spi=0x1020,nsh_si=255,actions=encap(ethernet),set_field:77:88:99:aa:bb:cc->dl_dst,goto_table:4 table=2,packet_type=(1,0x894f),nsh_spi=0x1020,nsh_si=254,actions=output:2010 table=4,dl_type=0x894f,dl_dst=11:22:33:44:55:66,actions=set_field:254->nsh_si,decap(),resubmit(,2) - table=4,dl_type=0x894f,dl_dst=77:88:99:aa:bb:cc,actions=set_field:254->nsh_si,decap(),resubmit(,2) + table=4,dl_type=0x894f,dl_dst=77:88:99:aa:bb:cc,actions=dec_nsh_ttl,decap(),resubmit(,2) ]) # br-in3 is SFC classifier (table 1) and final SFF (tables 2,3) @@ -607,7 +607,7 @@ AT_CHECK([ table=2, packet_type=(1,0x894f),nsh_spi=0x3020,nsh_si=254 actions=output:2030 table=2, packet_type=(1,0x894f),nsh_spi=0x3020,nsh_si=255 actions=encap(ethernet),set_field:11:22:33:44:55:66->eth_dst,goto_table:4 table=4, dl_dst=11:22:33:44:55:66,dl_type=0x894f actions=set_field:254->nsh_si,decap(),resubmit(,2) - table=4, dl_dst=77:88:99:aa:bb:cc,dl_type=0x894f actions=set_field:254->nsh_si,decap(),resubmit(,2) + table=4, dl_dst=77:88:99:aa:bb:cc,dl_type=0x894f actions=dec_nsh_ttl,decap(),resubmit(,2) ip,in_port=30 actions=decap(),goto_table:1 n_packets=2, n_bytes=216, packet_type=(1,0x894f),in_port=3010 actions=goto_table:2 packet_type=(1,0x800),in_port=30 actions=goto_table:1 @@ -661,7 +661,7 @@ AT_CHECK([ table=2, n_packets=2, n_bytes=216, packet_type=(1,0x894f),nsh_spi=0x3020,nsh_si=255 actions=encap(ethernet),set_field:11:22:33:44:55:66->eth_dst,goto_table:4 table=2, packet_type=(1,0x894f),nsh_spi=0x1020,nsh_si=254 actions=output:2010 table=2, packet_type=(1,0x894f),nsh_spi=0x1020,nsh_si=255 actions=encap(ethernet),set_field:77:88:99:aa:bb:cc->eth_dst,goto_table:4 - table=4, dl_dst=77:88:99:aa:bb:cc,dl_type=0x894f actions=set_field:254->nsh_si,decap(),resubmit(,2) + table=4, dl_dst=77:88:99:aa:bb:cc,dl_type=0x894f actions=dec_nsh_ttl,decap(),resubmit(,2) table=4, n_packets=2, n_bytes=216, dl_dst=11:22:33:44:55:66,dl_type=0x894f actions=set_field:254->nsh_si,decap(),resubmit(,2) ip,in_port=30 actions=decap(),goto_table:1 n_packets=2, n_bytes=216, packet_type=(1,0x894f),in_port=3010 actions=goto_table:2 diff --git a/utilities/ovs-ofctl.8.in b/utilities/ovs-ofctl.8.in index 5cdf48ce8..95344c7e3 100644 --- a/utilities/ovs-ofctl.8.in +++ b/utilities/ovs-ofctl.8.in @@ -1280,6 +1280,15 @@ Processing the current set of actions then stops. However, if the current set of actions was reached through ``resubmit'' then remaining actions in outer levels resume processing. . +.IP \fBdec_nsh_ttl\fR +Decrement TTL of the outer NSH header of a packet. If the TTL +is initially zero or decrementing would make it so, no decrement occurs. +Instead, a ``packet-in'' message with reason code \fBOFPR_INVALID_TTL\fR +is sent to the main controller (id zero), if it has enabled receiving them. +Processing the current set of actions then stops. However, if the current +set of actions was reached through ``resubmit'' then remaining actions in +outer levels resume processing. +. .IP \fBnote:\fR[\fIhh\fR]... Does nothing at all. Any number of bytes represented as hex digits \fIhh\fR may be included. Pairs of hex digits may be separated by @@ -1587,6 +1596,8 @@ the action set, the one written later replaces the earlier action: \fBdec_ttl\fR .IQ \fBdec_mpls_ttl\fR +.IQ +\fBdec_nsh_ttl\fR . .IP 7. \fBload\fR @@ -1647,7 +1658,7 @@ not visible.) .RE .IP Only the actions listed above may be written to the action set. -\fBencap\fR and \fBdecap\fR actions are nonstandard. +\fBencap\fR, \fBdecap\fR and \fBdec_nsh_ttl\fR actions are nonstandard. . .IP \fBwrite_metadata\fB:\fIvalue\fR[/\fImask\fR] Updates the metadata field for the flow. If \fImask\fR is omitted, the |