mirror of
https://github.com/openvswitch/ovs
synced 2025-08-22 01:51:26 +00:00
Add support for dec_mpls_ttl action
This adds support for the OpenFlow 1.1+ dec_mpls_ttl action. And also adds an NX dec_mpls_ttl action. The handling of the TTL modification is entirely handled in userspace. Reviewed-by: Isaku Yamahata <yamahata@valinux.co.jp> Signed-off-by: Simon Horman <horms@verge.net.au> Signed-off-by: Ben Pfaff <blp@nicira.com>
This commit is contained in:
parent
67a2f47310
commit
b676167a6f
3
NEWS
3
NEWS
@ -6,6 +6,9 @@ post-v1.10.0
|
||||
- New support for the data encapsulation format of the LISP tunnel
|
||||
protocol (RFC 6830). An external control plane or manual flow
|
||||
setup is required for EID-to-RLOC mapping.
|
||||
- OpenFlow:
|
||||
* The "dec_mpls_ttl" action from OpenFlow 1.1 and later is now
|
||||
implemented.
|
||||
|
||||
|
||||
v1.10.0 - xx xxx xxxx
|
||||
|
@ -306,6 +306,7 @@ enum nx_action_subtype {
|
||||
NXAST_WRITE_METADATA, /* struct nx_action_write_metadata */
|
||||
NXAST_PUSH_MPLS, /* struct nx_action_push_mpls */
|
||||
NXAST_POP_MPLS, /* struct nx_action_pop_mpls */
|
||||
NXAST_DEC_MPLS_TTL, /* struct nx_action_header */
|
||||
};
|
||||
|
||||
/* Header for Nicira-defined actions. */
|
||||
|
@ -848,6 +848,14 @@ flow_set_mpls_label(struct flow *flow, ovs_be32 label)
|
||||
set_mpls_lse_label(&flow->mpls_lse, label);
|
||||
}
|
||||
|
||||
/* Sets the MPLS TTL that 'flow' matches to 'ttl', which should be in the
|
||||
* range 0...255. */
|
||||
void
|
||||
flow_set_mpls_ttl(struct flow *flow, uint8_t ttl)
|
||||
{
|
||||
set_mpls_lse_ttl(&flow->mpls_lse, ttl);
|
||||
}
|
||||
|
||||
/* Sets the MPLS TC that 'flow' matches to 'tc', which should be in the
|
||||
* range 0...7. */
|
||||
void
|
||||
|
@ -406,6 +406,10 @@ ofpact_from_nxast(const union ofp_action *a, enum ofputil_action_code code,
|
||||
break;
|
||||
}
|
||||
|
||||
case OFPUTIL_NXAST_DEC_MPLS_TTL:
|
||||
ofpact_put_DEC_MPLS_TTL(out);
|
||||
break;
|
||||
|
||||
case OFPUTIL_NXAST_POP_MPLS: {
|
||||
struct nx_action_pop_mpls *nxapm = (struct nx_action_pop_mpls *)a;
|
||||
if (eth_type_mpls(nxapm->ethertype)) {
|
||||
@ -786,6 +790,10 @@ ofpact_from_openflow11(const union ofp_action *a, struct ofpbuf *out)
|
||||
return nxm_reg_load_from_openflow12_set_field(
|
||||
(const struct ofp12_action_set_field *)a, out);
|
||||
|
||||
case OFPUTIL_OFPAT11_DEC_MPLS_TTL:
|
||||
ofpact_put_DEC_MPLS_TTL(out);
|
||||
break;
|
||||
|
||||
case OFPUTIL_OFPAT11_PUSH_MPLS: {
|
||||
struct ofp11_action_push *oap = (struct ofp11_action_push *)a;
|
||||
if (!eth_type_mpls(oap->ethertype)) {
|
||||
@ -1136,6 +1144,7 @@ ofpact_check__(const struct ofpact *a, const struct flow *flow, int max_ports,
|
||||
}
|
||||
|
||||
case OFPACT_DEC_TTL:
|
||||
case OFPACT_DEC_MPLS_TTL:
|
||||
case OFPACT_SET_TUNNEL:
|
||||
case OFPACT_SET_QUEUE:
|
||||
case OFPACT_POP_QUEUE:
|
||||
@ -1383,6 +1392,10 @@ ofpact_to_nxast(const struct ofpact *a, struct ofpbuf *out)
|
||||
ofpact_dec_ttl_to_nxast(ofpact_get_DEC_TTL(a), out);
|
||||
break;
|
||||
|
||||
case OFPACT_DEC_MPLS_TTL:
|
||||
ofputil_put_NXAST_DEC_MPLS_TTL(out);
|
||||
break;
|
||||
|
||||
case OFPACT_SET_TUNNEL:
|
||||
ofpact_set_tunnel_to_nxast(ofpact_get_SET_TUNNEL(a), out);
|
||||
break;
|
||||
@ -1550,6 +1563,7 @@ ofpact_to_openflow10(const struct ofpact *a, struct ofpbuf *out)
|
||||
case OFPACT_REG_MOVE:
|
||||
case OFPACT_REG_LOAD:
|
||||
case OFPACT_DEC_TTL:
|
||||
case OFPACT_DEC_MPLS_TTL:
|
||||
case OFPACT_SET_TUNNEL:
|
||||
case OFPACT_WRITE_METADATA:
|
||||
case OFPACT_SET_QUEUE:
|
||||
@ -1682,6 +1696,10 @@ ofpact_to_openflow11(const struct ofpact *a, struct ofpbuf *out)
|
||||
ofpact_dec_ttl_to_openflow11(ofpact_get_DEC_TTL(a), out);
|
||||
break;
|
||||
|
||||
case OFPACT_DEC_MPLS_TTL:
|
||||
ofputil_put_OFPAT11_DEC_MPLS_TTL(out);
|
||||
break;
|
||||
|
||||
case OFPACT_WRITE_METADATA:
|
||||
/* OpenFlow 1.1 uses OFPIT_WRITE_METADATA to express this action. */
|
||||
break;
|
||||
@ -1826,6 +1844,7 @@ ofpact_outputs_to_port(const struct ofpact *ofpact, uint16_t port)
|
||||
case OFPACT_REG_MOVE:
|
||||
case OFPACT_REG_LOAD:
|
||||
case OFPACT_DEC_TTL:
|
||||
case OFPACT_DEC_MPLS_TTL:
|
||||
case OFPACT_SET_TUNNEL:
|
||||
case OFPACT_WRITE_METADATA:
|
||||
case OFPACT_SET_QUEUE:
|
||||
@ -2048,6 +2067,10 @@ ofpact_format(const struct ofpact *a, struct ds *s)
|
||||
print_dec_ttl(ofpact_get_DEC_TTL(a), s);
|
||||
break;
|
||||
|
||||
case OFPACT_DEC_MPLS_TTL:
|
||||
ds_put_cstr(s, "dec_mpls_ttl");
|
||||
break;
|
||||
|
||||
case OFPACT_SET_TUNNEL:
|
||||
tunnel = ofpact_get_SET_TUNNEL(a);
|
||||
ds_put_format(s, "set_tunnel%s:%#"PRIx64,
|
||||
|
@ -71,6 +71,7 @@
|
||||
DEFINE_OFPACT(REG_MOVE, ofpact_reg_move, ofpact) \
|
||||
DEFINE_OFPACT(REG_LOAD, ofpact_reg_load, ofpact) \
|
||||
DEFINE_OFPACT(DEC_TTL, ofpact_cnt_ids, cnt_ids) \
|
||||
DEFINE_OFPACT(DEC_MPLS_TTL, ofpact_null, ofpact) \
|
||||
DEFINE_OFPACT(PUSH_MPLS, ofpact_push_mpls, ofpact) \
|
||||
DEFINE_OFPACT(POP_MPLS, ofpact_pop_mpls, ofpact) \
|
||||
\
|
||||
|
@ -550,6 +550,11 @@ parse_named_action(enum ofputil_action_code code, const struct flow *flow,
|
||||
parse_dec_ttl(ofpacts, arg);
|
||||
break;
|
||||
|
||||
case OFPUTIL_OFPAT11_DEC_MPLS_TTL:
|
||||
case OFPUTIL_NXAST_DEC_MPLS_TTL:
|
||||
ofpact_put_DEC_MPLS_TTL(ofpacts);
|
||||
break;
|
||||
|
||||
case OFPUTIL_NXAST_FIN_TIMEOUT:
|
||||
parse_fin_timeout(ofpacts, arg);
|
||||
break;
|
||||
|
@ -30,6 +30,7 @@ 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_DEC_MPLS_TTL, ofp_action_header, 0, "dec_mpls_ttl")
|
||||
OFPAT11_ACTION(OFPAT11_PUSH_VLAN, ofp11_action_push, 0, "push_vlan")
|
||||
OFPAT11_ACTION(OFPAT11_POP_VLAN, ofp_action_header, 0, "pop_vlan")
|
||||
OFPAT11_ACTION(OFPAT11_PUSH_MPLS, ofp11_action_push, 0, "push_mpls")
|
||||
@ -63,6 +64,7 @@ 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_DEC_MPLS_TTL, nx_action_header, 0, "dec_mpls_ttl")
|
||||
NXAST_ACTION(NXAST_PUSH_MPLS, nx_action_push_mpls, 0, "push_mpls")
|
||||
NXAST_ACTION(NXAST_POP_MPLS, nx_action_pop_mpls, 0, "pop_mpls")
|
||||
|
||||
|
@ -259,7 +259,7 @@ static bool is_mpls(struct ofpbuf *packet)
|
||||
}
|
||||
|
||||
/* Set time to live (TTL) of an MPLS label stack entry (LSE). */
|
||||
static void
|
||||
void
|
||||
set_mpls_lse_ttl(ovs_be32 *lse, uint8_t ttl)
|
||||
{
|
||||
*lse &= ~htonl(MPLS_TTL_MASK);
|
||||
|
@ -155,6 +155,7 @@ void set_mpls_lse(struct ofpbuf *, ovs_be32 label);
|
||||
void push_mpls(struct ofpbuf *packet, ovs_be16 ethtype, ovs_be32 lse);
|
||||
void pop_mpls(struct ofpbuf *, ovs_be16 ethtype);
|
||||
|
||||
void set_mpls_lse_ttl(ovs_be32 *lse, uint8_t ttl);
|
||||
void set_mpls_lse_tc(ovs_be32 *lse, uint8_t tc);
|
||||
void set_mpls_lse_label(ovs_be32 *lse, ovs_be32 label);
|
||||
void set_mpls_lse_bos(ovs_be32 *lse, uint8_t bos);
|
||||
|
@ -6058,6 +6058,27 @@ compose_dec_ttl(struct action_xlate_ctx *ctx, struct ofpact_cnt_ids *ids)
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
execute_dec_mpls_ttl_action(struct action_xlate_ctx *ctx)
|
||||
{
|
||||
uint8_t ttl = mpls_lse_to_ttl(ctx->flow.mpls_lse);
|
||||
|
||||
if (!eth_type_mpls(ctx->flow.dl_type)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ttl > 0) {
|
||||
ttl--;
|
||||
set_mpls_lse_ttl(&ctx->flow.mpls_lse, ttl);
|
||||
return false;
|
||||
} else {
|
||||
execute_controller_action(ctx, UINT16_MAX, OFPR_INVALID_TTL, 0);
|
||||
|
||||
/* Stop processing for current table. */
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
xlate_output_action(struct action_xlate_ctx *ctx,
|
||||
uint16_t port, uint16_t max_len, bool may_packet_in)
|
||||
@ -6401,6 +6422,12 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len,
|
||||
execute_mpls_pop_action(ctx, ofpact_get_POP_MPLS(a)->ethertype);
|
||||
break;
|
||||
|
||||
case OFPACT_DEC_MPLS_TTL:
|
||||
if (execute_dec_mpls_ttl_action(ctx)) {
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
|
||||
case OFPACT_DEC_TTL:
|
||||
if (compose_dec_ttl(ctx, ofpact_get_DEC_TTL(a))) {
|
||||
goto out;
|
||||
|
@ -233,6 +233,7 @@ cookie=0x9 table=7 in_port=86 actions=mod_tp_dst:86,controller,controller
|
||||
cookie=0xa dl_src=40:44:44:44:44:42 actions=push_mpls:0x8847,load:10->OXM_OF_MPLS_LABEL[[]],load:3->OXM_OF_MPLS_TC[[]],controller
|
||||
cookie=0xa dl_src=40:44:44:44:44:43 actions=push_mpls:0x8847,load:10->OXM_OF_MPLS_LABEL[[]],load:3->OXM_OF_MPLS_TC[[]],controller
|
||||
cookie=0xa dl_src=40:44:44:44:44:44 actions=push_mpls:0x8847,load:10->OXM_OF_MPLS_LABEL[[]],load:3->OXM_OF_MPLS_TC[[]],controller
|
||||
cookie=0xa dl_src=40:44:44:44:44:45 actions=push_mpls:0x8847,load:10->OXM_OF_MPLS_LABEL[[]],load:3->OXM_OF_MPLS_TC[[]],dec_mpls_ttl,controller
|
||||
cookie=0xb dl_src=50:55:55:55:55:55 dl_type=0x8847 actions=load:1000->OXM_OF_MPLS_LABEL[[]],controller
|
||||
cookie=0xd dl_src=60:66:66:66:66:66 actions=pop_mpls:0x0800,controller
|
||||
cookie=0xc dl_src=70:77:77:77:77:77 actions=push_mpls:0x8848,load:1000->OXM_OF_MPLS_LABEL[[]],load:7->OXM_OF_MPLS_TC[[]],controller
|
||||
@ -355,6 +356,25 @@ NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len
|
||||
mpls(label:10,tc:3,ttl:64,bos:1),metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=7,dl_src=40:44:44:44:44:44,dl_dst=50:54:00:00:00:07
|
||||
])
|
||||
|
||||
dnl Modified MPLS controller action.
|
||||
AT_CHECK([ovs-ofctl monitor br0 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:44:45,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=64 in_port=1 (via action) data_len=64 (unbuffered)
|
||||
mpls(label:10,tc:3,ttl:63,bos:1),metadata=0,in_port=0,vlan_tci=0x0000,dl_src=40:44:44:44:44:45,dl_dst=50:54:00:00:00:07
|
||||
dnl
|
||||
NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered)
|
||||
mpls(label:10,tc:3,ttl:63,bos:1),metadata=0,in_port=0,vlan_tci=0x0000,dl_src=40:44:44:44:44:45,dl_dst=50:54:00:00:00:07
|
||||
dnl
|
||||
NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered)
|
||||
mpls(label:10,tc:3,ttl:63,bos:1),metadata=0,in_port=0,vlan_tci=0x0000,dl_src=40:44:44:44:44:45,dl_dst=50:54:00:00:00:07
|
||||
])
|
||||
|
||||
dnl Modified MPLS actions.
|
||||
AT_CHECK([ovs-ofctl monitor br0 65534 -P nxm --detach --pidfile 2> ofctl_monitor.log])
|
||||
|
||||
@ -500,6 +520,7 @@ 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:44:42 actions=push_mpls:0x8847,load:0xa->OXM_OF_MPLS_LABEL[[]],load:0x3->OXM_OF_MPLS_TC[[]],CONTROLLER:65535
|
||||
cookie=0xa, n_packets=3, n_bytes=180, dl_src=40:44:44:44:44:43 actions=push_mpls:0x8847,load:0xa->OXM_OF_MPLS_LABEL[[]],load:0x3->OXM_OF_MPLS_TC[[]],CONTROLLER:65535
|
||||
cookie=0xa, n_packets=3, n_bytes=180, dl_src=40:44:44:44:44:44 actions=push_mpls:0x8847,load:0xa->OXM_OF_MPLS_LABEL[[]],load:0x3->OXM_OF_MPLS_TC[[]],CONTROLLER:65535
|
||||
cookie=0xa, n_packets=3, n_bytes=180, dl_src=40:44:44:44:44:45 actions=push_mpls:0x8847,load:0xa->OXM_OF_MPLS_LABEL[[]],load:0x3->OXM_OF_MPLS_TC[[]],dec_mpls_ttl,CONTROLLER:65535
|
||||
cookie=0xb, n_packets=3, n_bytes=180, dl_src=50:55:55:55:55:55,dl_type=0x8847 actions=load:0x3e8->OXM_OF_MPLS_LABEL[[]],CONTROLLER:65535
|
||||
cookie=0xc, n_packets=3, n_bytes=180, dl_src=70:77:77:77:77:77 actions=push_mpls:0x8848,load:0x3e8->OXM_OF_MPLS_LABEL[[]],load:0x7->OXM_OF_MPLS_TC[[]],CONTROLLER:65535
|
||||
cookie=0xd, n_packets=3, n_bytes=180, dl_src=60:66:66:66:66:66 actions=pop_mpls:0x0800,CONTROLLER:65535
|
||||
|
@ -1018,6 +1018,15 @@ invalid ttl packets. If controller ids are not specified, the
|
||||
``packet_in'' message will be sent only to the controllers having
|
||||
controller id zero which have registered for the invalid ttl packets.
|
||||
.
|
||||
.IP \fBdec_mpls_ttl\fR
|
||||
Decrement TTL of the outer MPLS label stack entry of a packet. If the TTL
|
||||
is initially zero, no decrement occurs. Instead, a ``packet-in'' message
|
||||
with reason code \fBOFPR_INVALID_TTL\fR is sent to each connected
|
||||
controller with controller id zer that 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
|
||||
|
Loading…
x
Reference in New Issue
Block a user