[ovs-dev] [PATCH 15/16] Add support for copy_ttl_out action
Simon Horman
horms at verge.net.au
Thu Jan 3 02:53:49 UTC 2013
This adds support for the OpenFlow 1.1+ copy_ttl_out action.
And also adds an NX copy_ttl_out action.
The implementation does not support copying in the case where the outermost
header is IP as it is unclear to me that Open vSwtich has a notion of an
inner IP header to copy the TLL from.
The handling of the TTL modification is entirely handled in userspace.
Reviewed-by: Isaku Yamahata <yamahata at valinux.co.jp>
Signed-off-by: Simon Horman <horms at verge.net.au>
---
v2.13
* Remove bogus test. copy_ttl_out from IP to MPLS only makes sense
if the dl_type of the encapsulated frame is known, which implies
that the original frame was IP and an mpls_push action has been applied.
v2.12
* No change
v2.10
* No change
v2.9
* Increment FLOW_WC_SEQ
* Update tests for upstream changes
v2.8
* No change
v2.7
* Encode action as OFP11 action in OFP11+ messages
v2.6
* Non-trivial rebase
v2.5
* First post
---
include/openflow/nicira-ext.h | 1 +
lib/flow.c | 6 ++++--
lib/flow.h | 7 ++++---
lib/match.c | 2 +-
lib/nx-match.c | 2 +-
lib/ofp-actions.c | 23 +++++++++++++++++++++++
lib/ofp-actions.h | 1 +
lib/ofp-parse.c | 5 +++++
lib/ofp-util.c | 4 ++--
lib/ofp-util.def | 2 ++
ofproto/ofproto-dpif.c | 23 +++++++++++++++++++++++
tests/ofproto-dpif.at | 23 ++++++++++++++++++++++-
utilities/ovs-ofctl.8.in | 7 +++++++
13 files changed, 96 insertions(+), 10 deletions(-)
diff --git a/include/openflow/nicira-ext.h b/include/openflow/nicira-ext.h
index bc7fb1e..a682e60 100644
--- a/include/openflow/nicira-ext.h
+++ b/include/openflow/nicira-ext.h
@@ -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_COPY_TTL_OUT, /* struct nx_action_header */
NXAST_SET_MPLS_TTL, /* struct nx_action_ttl */
NXAST_DEC_MPLS_TTL, /* struct nx_action_header */
};
diff --git a/lib/flow.c b/lib/flow.c
index 2af94fa..674e451 100644
--- a/lib/flow.c
+++ b/lib/flow.c
@@ -100,7 +100,9 @@ parse_remaining_mpls(struct ofpbuf *b, struct flow *flow)
struct mpls_hdr *mh;
while ((mh = ofpbuf_try_pull(b, sizeof *mh)) &&
!(mh->mpls_lse & htonl(MPLS_BOS_MASK))) {
- flow->mpls_depth++;
+ if (flow->mpls_depth++ == 1) {
+ flow->inner_mpls_lse = mh->mpls_lse;
+ }
}
}
@@ -522,7 +524,7 @@ flow_zero_wildcards(struct flow *flow, const struct flow_wildcards *wildcards)
void
flow_get_metadata(const struct flow *flow, struct flow_metadata *fmd)
{
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 19);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 20);
fmd->tun_id = flow->tunnel.tun_id;
fmd->metadata = flow->metadata;
diff --git a/lib/flow.h b/lib/flow.h
index 3078332..07b9f8b 100644
--- a/lib/flow.h
+++ b/lib/flow.h
@@ -36,7 +36,7 @@ struct ofpbuf;
/* This sequence number should be incremented whenever anything involving flows
* or the wildcarding of flows changes. This will cause build assertion
* failures in places which likely need to be updated. */
-#define FLOW_WC_SEQ 19
+#define FLOW_WC_SEQ 20
#define FLOW_N_REGS 8
BUILD_ASSERT_DECL(FLOW_N_REGS <= NXM_NX_MAX_REGS);
@@ -92,6 +92,7 @@ struct flow {
is the datapath port number. */
uint32_t skb_mark; /* Packet mark. */
ovs_be32 mpls_lse; /* MPLS label stack entry. */
+ ovs_be32 inner_mpls_lse; /* Inner MPLS label stack entry. */
uint16_t mpls_depth; /* Depth of MPLS stack. */
ovs_be16 vlan_tci; /* If 802.1Q, TCI | VLAN_CFI; otherwise 0. */
ovs_be16 dl_type; /* Ethernet frame type. */
@@ -106,7 +107,7 @@ struct flow {
uint8_t arp_tha[6]; /* ARP/ND target hardware address. */
uint8_t nw_ttl; /* IP TTL/Hop Limit. */
uint8_t nw_frag; /* FLOW_FRAG_* flags. */
- uint8_t zeros[4];
+ uint8_t zeros[0];
};
BUILD_ASSERT_DECL(sizeof(struct flow) % 4 == 0);
@@ -114,7 +115,7 @@ BUILD_ASSERT_DECL(sizeof(struct flow) % 4 == 0);
/* Remember to update FLOW_WC_SEQ when changing 'struct flow'. */
BUILD_ASSERT_DECL(sizeof(struct flow) == sizeof(struct flow_tnl) + 160 &&
- FLOW_WC_SEQ == 19);
+ FLOW_WC_SEQ == 20);
/* Represents the metadata fields of struct flow. */
struct flow_metadata {
diff --git a/lib/match.c b/lib/match.c
index 5cab7f0..3824a4b 100644
--- a/lib/match.c
+++ b/lib/match.c
@@ -851,7 +851,7 @@ match_format(const struct match *match, struct ds *s, unsigned int priority)
int i;
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 19);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 20);
if (priority != OFP_DEFAULT_PRIORITY) {
ds_put_format(s, "priority=%u,", priority);
diff --git a/lib/nx-match.c b/lib/nx-match.c
index 64b93a4..c364ea5 100644
--- a/lib/nx-match.c
+++ b/lib/nx-match.c
@@ -573,7 +573,7 @@ nx_put_raw(struct ofpbuf *b, bool oxm, const struct match *match,
int match_len;
int i;
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 19);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 20);
/* Metadata. */
if (match->wc.masks.in_port) {
diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c
index 58eae55..f3bbc51 100644
--- a/lib/ofp-actions.c
+++ b/lib/ofp-actions.c
@@ -411,6 +411,10 @@ ofpact_from_nxast(const union ofp_action *a, enum ofputil_action_code code,
break;
}
+ case OFPUTIL_NXAST_COPY_TTL_OUT:
+ ofpact_put_COPY_TTL_OUT(out);
+ break;
+
case OFPUTIL_NXAST_SET_MPLS_TTL: {
struct nx_action_mpls_ttl *nxamt = (struct nx_action_mpls_ttl *)a;
ofpact_put_SET_MPLS_TTL(out)->ttl = nxamt->ttl;
@@ -801,6 +805,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_COPY_TTL_OUT:
+ ofpact_put_COPY_TTL_OUT(out);
+ break;
+
case OFPUTIL_OFPAT11_SET_MPLS_TTL: {
struct ofp11_action_mpls_ttl *oamt = (struct ofp11_action_mpls_ttl *)a;
ofpact_put_SET_MPLS_TTL(out)->ttl = oamt->mpls_ttl;
@@ -1161,6 +1169,7 @@ ofpact_check__(const struct ofpact *a, const struct flow *flow, int max_ports,
}
case OFPACT_DEC_TTL:
+ case OFPACT_COPY_TTL_OUT:
case OFPACT_SET_MPLS_TTL:
case OFPACT_DEC_MPLS_TTL:
case OFPACT_SET_TUNNEL:
@@ -1399,6 +1408,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_COPY_TTL_OUT:
+ ofputil_put_NXAST_COPY_TTL_OUT(out);
+ break;
+
case OFPACT_SET_MPLS_TTL:
ofputil_put_NXAST_SET_MPLS_TTL(out)->ttl
= ofpact_get_SET_MPLS_TTL(a)->ttl;
@@ -1579,6 +1592,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_COPY_TTL_OUT:
case OFPACT_SET_MPLS_TTL:
case OFPACT_DEC_MPLS_TTL:
case OFPACT_SET_TUNNEL:
@@ -1714,6 +1728,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_COPY_TTL_OUT:
+ ofputil_put_OFPAT11_COPY_TTL_OUT(out);
+ break;
+
case OFPACT_SET_MPLS_TTL:
ofputil_put_OFPAT11_SET_MPLS_TTL(out)->mpls_ttl
= ofpact_get_SET_MPLS_TTL(a)->ttl;
@@ -1868,6 +1886,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_COPY_TTL_OUT:
case OFPACT_SET_MPLS_TTL:
case OFPACT_DEC_MPLS_TTL:
case OFPACT_SET_TUNNEL:
@@ -2094,6 +2113,10 @@ ofpact_format(const struct ofpact *a, struct ds *s)
print_dec_ttl(ofpact_get_DEC_TTL(a), s);
break;
+ case OFPACT_COPY_TTL_OUT:
+ ds_put_cstr(s, "copy_ttl_out");
+ break;
+
case OFPACT_SET_MPLS_TTL:
ds_put_format(s, "set_mpls_ttl(%"PRIu8")",
ofpact_get_SET_MPLS_TTL(a)->ttl);
diff --git a/lib/ofp-actions.h b/lib/ofp-actions.h
index f5f02ee..ed425f3 100644
--- a/lib/ofp-actions.h
+++ b/lib/ofp-actions.h
@@ -73,6 +73,7 @@
DEFINE_OFPACT(DEC_TTL, ofpact_cnt_ids, cnt_ids) \
DEFINE_OFPACT(SET_MPLS_TTL, ofpact_mpls_ttl, ofpact) \
DEFINE_OFPACT(DEC_MPLS_TTL, ofpact_null, ofpact) \
+ DEFINE_OFPACT(COPY_TTL_OUT, ofpact_null, ofpact) \
DEFINE_OFPACT(PUSH_MPLS, ofpact_push, ofpact) \
DEFINE_OFPACT(POP_MPLS, ofpact_pop_mpls, ofpact) \
\
diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c
index b7db256..af7a88f 100644
--- a/lib/ofp-parse.c
+++ b/lib/ofp-parse.c
@@ -577,6 +577,11 @@ parse_named_action(enum ofputil_action_code code, const struct flow *flow,
ofpact_put_DEC_MPLS_TTL(ofpacts);
break;
+ case OFPUTIL_OFPAT11_COPY_TTL_OUT:
+ case OFPUTIL_NXAST_COPY_TTL_OUT:
+ ofpact_put_COPY_TTL_OUT(ofpacts);
+ break;
+
case OFPUTIL_NXAST_FIN_TIMEOUT:
parse_fin_timeout(ofpacts, arg);
break;
diff --git a/lib/ofp-util.c b/lib/ofp-util.c
index 8de641f..83e50e4 100644
--- a/lib/ofp-util.c
+++ b/lib/ofp-util.c
@@ -85,7 +85,7 @@ ofputil_netmask_to_wcbits(ovs_be32 netmask)
void
ofputil_wildcard_from_ofpfw10(uint32_t ofpfw, struct flow_wildcards *wc)
{
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 19);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 20);
/* Initialize most of wc. */
flow_wildcards_init_catchall(wc);
@@ -1059,7 +1059,7 @@ ofputil_usable_protocols(const struct match *match)
{
const struct flow_wildcards *wc = &match->wc;
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 19);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 20);
/* tunnel params other than tun_id can't be sent in a flow_mod */
if (!tun_parms_fully_wildcarded(wc)) {
diff --git a/lib/ofp-util.def b/lib/ofp-util.def
index 83b5580..a598a02 100644
--- a/lib/ofp-util.def
+++ b/lib/ofp-util.def
@@ -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_COPY_TTL_OUT, ofp_action_header, 0, "copy_ttl_out")
OFPAT11_ACTION(OFPAT11_SET_MPLS_TTL, ofp11_action_mpls_ttl, 0, "set_mpls_ttl")
OFPAT11_ACTION(OFPAT11_DEC_MPLS_TTL, ofp_action_header, 0, "dec_mpls_ttl")
OFPAT11_ACTION(OFPAT11_PUSH_VLAN, ofp11_action_push, 0, "push_vlan")
@@ -66,6 +67,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_COPY_TTL_OUT, nx_action_header, 0, "copy_ttl_out")
NXAST_ACTION(NXAST_SET_MPLS_TTL, nx_action_mpls_ttl, 0, "set_mpls_ttl")
NXAST_ACTION(NXAST_DEC_MPLS_TTL, nx_action_header, 0, "dec_mpls_ttl")
NXAST_ACTION(NXAST_PUSH_MPLS, nx_action_push, 0, "push_mpls")
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index f6939a4..3b2f9c0 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -5809,6 +5809,25 @@ compose_dec_ttl(struct action_xlate_ctx *ctx, struct ofpact_cnt_ids *ids)
}
static void
+compose_copy_ttl_out_action(struct action_xlate_ctx *ctx)
+{
+ if (ctx->flow.dl_type != htons(ETH_TYPE_MPLS) &&
+ ctx->flow.dl_type != htons(ETH_TYPE_MPLS_MCAST)) {
+ /* Copying TTL to IP is not supported */
+ return;
+ }
+
+ if (ctx->flow.mpls_depth > 1) {
+ /* MPLS -> MPLS */
+ set_mpls_lse_ttl(&ctx->flow.mpls_lse,
+ mpls_lse_to_ttl(ctx->flow.inner_mpls_lse));
+ } else {
+ /* IP -> MPLS */
+ set_mpls_lse_ttl(&ctx->flow.mpls_lse, ctx->flow.nw_ttl);
+ }
+}
+
+static void
compose_set_mpls_ttl_action(struct action_xlate_ctx *ctx, uint8_t ttl)
{
if (eth_type_mpls(ctx->flow.dl_type)) {
@@ -6207,6 +6226,10 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len,
compose_mpls_pop_action(ctx, ofpact_get_POP_MPLS(a)->ethertype);
break;
+ case OFPACT_COPY_TTL_OUT:
+ compose_copy_ttl_out_action(ctx);
+ break;
+
case OFPACT_SET_MPLS_TTL:
compose_set_mpls_ttl_action(ctx, ofpact_get_SET_MPLS_TTL(a)->ttl);
break;
diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at
index 06f082d..f8a5ad5 100644
--- a/tests/ofproto-dpif.at
+++ b/tests/ofproto-dpif.at
@@ -254,6 +254,7 @@ cookie=0xa dl_src=40:44:44:44:44:45 actions=push_mpls:0x8847,load:10->OXM_OF_MPL
cookie=0xa dl_src=40:44:44:44:44:46 actions=push_mpls:0x8847,load:10->OXM_OF_MPLS_LABEL[[]],load:3->OXM_OF_MPLS_TC[[]],set_mpls_ttl(10),controller
cookie=0xa dl_src=40:44:44:44:44:47 actions=push_mpls:0x8847,load:10->OXM_OF_MPLS_LABEL[[]],load:3->OXM_OF_MPLS_TC[[]],dec_mpls_ttl,set_mpls_ttl(10),controller
cookie=0xa dl_src=40:44:44:44:44:48 actions=push_mpls:0x8847,load:10->OXM_OF_MPLS_LABEL[[]],load:3->OXM_OF_MPLS_TC[[]],set_mpls_ttl(10),dec_mpls_ttl,controller
+cookie=0xa dl_src=40:44:44:44:44:49 actions=push_mpls:0x8847,load:10->OXM_OF_MPLS_LABEL[[]],load:3->OXM_OF_MPLS_TC[[]],set_mpls_ttl(10),dec_mpls_ttl,copy_ttl_out,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
@@ -397,6 +398,26 @@ 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:49,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:64,bos:1),metadata=0,in_port=0,vlan_tci=0x0000,dl_src=40:44:44:44:44:49,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:64,bos:1),metadata=0,in_port=0,vlan_tci=0x0000,dl_src=40:44:44:44:44:49,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:64,bos:1),metadata=0,in_port=0,vlan_tci=0x0000,dl_src=40:44:44:44:44:49,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:48,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
@@ -450,7 +471,6 @@ NXT_PACKET_IN (xid=0x0): cookie=0xc total_len=64 in_port=1 (via action) data_len
mplsm(label:1000,tc:7,ttl:64,bos:1),metadata=0,in_port=0,vlan_tci=0x0000,dl_src=70:77:77:77:77:77,dl_dst=50:54:00:00:00:07
])
-
dnl Modified MPLS pop action.
AT_CHECK([ovs-ofctl monitor br0 65534 -P nxm --detach --pidfile 2> ofctl_monitor.log])
@@ -559,6 +579,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:46 actions=push_mpls:0x8847,load:0xa->OXM_OF_MPLS_LABEL[[]],load:0x3->OXM_OF_MPLS_TC[[]],set_mpls_ttl(10),CONTROLLER:65535
cookie=0xa, n_packets=3, n_bytes=180, dl_src=40:44:44:44:44:47 actions=push_mpls:0x8847,load:0xa->OXM_OF_MPLS_LABEL[[]],load:0x3->OXM_OF_MPLS_TC[[]],dec_mpls_ttl,set_mpls_ttl(10),CONTROLLER:65535
cookie=0xa, n_packets=3, n_bytes=180, dl_src=40:44:44:44:44:48 actions=push_mpls:0x8847,load:0xa->OXM_OF_MPLS_LABEL[[]],load:0x3->OXM_OF_MPLS_TC[[]],set_mpls_ttl(10),dec_mpls_ttl,CONTROLLER:65535
+ cookie=0xa, n_packets=3, n_bytes=180, dl_src=40:44:44:44:44:49 actions=push_mpls:0x8847,load:0xa->OXM_OF_MPLS_LABEL[[]],load:0x3->OXM_OF_MPLS_TC[[]],set_mpls_ttl(10),dec_mpls_ttl,copy_ttl_out,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
diff --git a/utilities/ovs-ofctl.8.in b/utilities/ovs-ofctl.8.in
index 06627fe..819d350 100644
--- a/utilities/ovs-ofctl.8.in
+++ b/utilities/ovs-ofctl.8.in
@@ -1022,6 +1022,13 @@ 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 \fBcopy_ttl_out\fR
+Copy the TTL from the next-to-outermost to the outermost header with TTL.
+The implementation supports copying to an outer MPLS header from either the
+next-to-outermost MPLS header, or if the MPLS stack only has a depth of one
+the TTL of the outer-most IP header - the TTL of an IPv4 header or hop limit
+of an IPv6 header.
+.
.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
--
1.7.10.4
More information about the dev
mailing list