2
0
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:
Simon Horman 2013-03-06 16:08:23 +09:00 committed by Ben Pfaff
parent 67a2f47310
commit b676167a6f
12 changed files with 102 additions and 1 deletions

3
NEWS
View File

@ -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

View File

@ -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. */

View File

@ -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

View File

@ -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,

View File

@ -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) \
\

View File

@ -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;

View File

@ -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")

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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