[ovs-dev] [PATCH 09/15] Add support for copy_ttl_in action

Simon Horman horms at verge.net.au
Fri Feb 15 09:56:03 UTC 2013


This adds support for the OpenFlow 1.1+ copy_ttl_in 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 implementation does not support copying in the case where the
outermost and next-to-otermost header is MPLS due to limitations
in the current MPLS implementation which only supports modifying
the outermost MPLS header.

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.19
* Rebase
* Do not allow setting of TTL to zero
* Treat this and other illegal conditions
  as grounds to stop a flow's actions.
* Update to preserve nw_ttl on execute_mpls_pop_action()
  This is needed now that prior patches use xlate_actions
  for l3 decoding of MPLS frames.
* Update test to use encap()

v2.18
* No change

v2.17
* As suggested by Ben Pfaff
  - Rename execute_copy_ttl_in_action functions as compose_copy_ttl_in_action

v2.13 - v2.16
* No change

v2.12
* Rebase
* Use eth_type_mpls() helper

v2.10 - v2.11
* No change

v2.9
* Update tests for upstream changes

v2.8
* No change

v2.7
* Correct typo in changelog
* Encode action as OFP11 action in OFP11+ messages

v2.6
* Non-trivial rebase

v2.5
* First post
---
 include/openflow/nicira-ext.h |    1 +
 lib/match.c                   |    2 +-
 lib/ofp-actions.c             |   23 ++++++++++++++++++++++
 lib/ofp-actions.h             |    1 +
 lib/ofp-parse.c               |    5 +++++
 lib/ofp-print.c               |    4 +++-
 lib/ofp-util.def              |    2 ++
 ofproto/ofproto-dpif.c        |   42 +++++++++++++++++++++++++++++++++++++++++
 tests/ofproto-dpif.at         |   21 +++++++++++++++++++++
 utilities/ovs-ofctl.8.in      |    5 +++++
 10 files changed, 104 insertions(+), 2 deletions(-)

diff --git a/include/openflow/nicira-ext.h b/include/openflow/nicira-ext.h
index a6930fd..8091b2d 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_IN,          /* struct nx_action_header */
     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/match.c b/lib/match.c
index c47c70a..74fe3bb 100644
--- a/lib/match.c
+++ b/lib/match.c
@@ -994,7 +994,7 @@ match_format(const struct match *match, struct ds *s, unsigned int priority)
         if (f->dl_type == htons(ETH_TYPE_ARP) ||
             f->dl_type == htons(ETH_TYPE_RARP)) {
             ds_put_format(s, "arp_op=%"PRIu8",", f->nw_proto);
-        } else {
+        } else if (!eth_type_mpls(f->dl_type)) {
             ds_put_format(s, "nw_proto=%"PRIu8",", f->nw_proto);
         }
     }
diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c
index 74631e4..5b15a11 100644
--- a/lib/ofp-actions.c
+++ b/lib/ofp-actions.c
@@ -406,6 +406,10 @@ ofpact_from_nxast(const union ofp_action *a, enum ofputil_action_code code,
         break;
     }
 
+    case OFPUTIL_NXAST_COPY_TTL_IN:
+        ofpact_put_COPY_TTL_IN(out);
+        break;
+
     case OFPUTIL_NXAST_COPY_TTL_OUT:
         ofpact_put_COPY_TTL_OUT(out);
         break;
@@ -800,6 +804,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_IN:
+        ofpact_put_COPY_TTL_IN(out);
+        break;
+
     case OFPUTIL_OFPAT11_COPY_TTL_OUT:
         ofpact_put_COPY_TTL_OUT(out);
         break;
@@ -1164,6 +1172,7 @@ ofpact_check__(const struct ofpact *a, const struct flow *flow, int max_ports,
         }
 
     case OFPACT_DEC_TTL:
+    case OFPACT_COPY_TTL_IN:
     case OFPACT_COPY_TTL_OUT:
     case OFPACT_SET_MPLS_TTL:
     case OFPACT_DEC_MPLS_TTL:
@@ -1414,6 +1423,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_IN:
+        ofputil_put_NXAST_COPY_TTL_IN(out);
+        break;
+
     case OFPACT_COPY_TTL_OUT:
         ofputil_put_NXAST_COPY_TTL_OUT(out);
         break;
@@ -1594,6 +1607,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_IN:
     case OFPACT_COPY_TTL_OUT:
     case OFPACT_SET_MPLS_TTL:
     case OFPACT_DEC_MPLS_TTL:
@@ -1729,6 +1743,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_IN:
+        ofputil_put_OFPAT11_COPY_TTL_IN(out);
+        break;
+
     case OFPACT_COPY_TTL_OUT:
         ofputil_put_OFPAT11_COPY_TTL_OUT(out);
         break;
@@ -1886,6 +1904,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_IN:
     case OFPACT_COPY_TTL_OUT:
     case OFPACT_SET_MPLS_TTL:
     case OFPACT_DEC_MPLS_TTL:
@@ -2111,6 +2130,10 @@ ofpact_format(const struct ofpact *a, struct ds *s)
         print_dec_ttl(ofpact_get_DEC_TTL(a), s);
         break;
 
+    case OFPACT_COPY_TTL_IN:
+        ds_put_cstr(s, "copy_ttl_in");
+        break;
+
     case OFPACT_COPY_TTL_OUT:
         ds_put_cstr(s, "copy_ttl_out");
         break;
diff --git a/lib/ofp-actions.h b/lib/ofp-actions.h
index d76073f..a4372b6 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_IN,     ofpact_null,          ofpact)    \
     DEFINE_OFPACT(COPY_TTL_OUT,    ofpact_null,          ofpact)    \
     DEFINE_OFPACT(PUSH_MPLS,       ofpact_push_mpls,     ofpact)    \
     DEFINE_OFPACT(POP_MPLS,        ofpact_pop_mpls,      ofpact)    \
diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c
index 69daa99..b9a333a 100644
--- a/lib/ofp-parse.c
+++ b/lib/ofp-parse.c
@@ -572,6 +572,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_IN:
+    case OFPUTIL_NXAST_COPY_TTL_IN:
+        ofpact_put_COPY_TTL_IN(ofpacts);
+        break;
+
     case OFPUTIL_OFPAT11_COPY_TTL_OUT:
     case OFPUTIL_NXAST_COPY_TTL_OUT:
         ofpact_put_COPY_TTL_OUT(ofpacts);
diff --git a/lib/ofp-print.c b/lib/ofp-print.c
index f7872cb..cfa09a7 100644
--- a/lib/ofp-print.c
+++ b/lib/ofp-print.c
@@ -66,7 +66,7 @@ ofp_packet_to_string(const void *data, size_t len)
     flow_extract(&buf, 0, 0, NULL, 0, &flow);
     flow_format(&ds, &flow);
 
-    if (buf.l7) {
+    if (buf.l7 && !eth_type_mpls(flow.dl_type)) {
         if (flow.nw_proto == IPPROTO_TCP) {
             struct tcp_header *th = buf.l4;
             ds_put_format(&ds, " tcp_csum:%"PRIx16,
@@ -644,8 +644,10 @@ ofp10_match_to_string(const struct ofp10_match *om, int verbosity)
             ds_put_cstr(&f, "rarp,");
         } else if (om->dl_type == htons(ETH_TYPE_MPLS)) {
             ds_put_cstr(&f, "mpls,");
+            skip_proto = true;
         } else if (om->dl_type == htons(ETH_TYPE_MPLS_MCAST)) {
             ds_put_cstr(&f, "mplsm,");
+            skip_proto = true;
         } else {
             skip_type = false;
         }
diff --git a/lib/ofp-util.def b/lib/ofp-util.def
index d3f6deb..6e7b18d 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_IN,  ofp_action_header,   0, "copy_ttl_in")
 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")
@@ -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_IN,     nx_action_header,       0, "copy_ttl_in")
 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")
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index 92c9087..99a5972 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -6119,9 +6119,17 @@ execute_mpls_pop_action(struct action_xlate_ctx *ctx, ovs_be16 eth_type)
             ctx->base_flow.encap_dl_type = ctx->flow.dl_type = eth_type;
             ctx->flow.encap_dl_type = htons(0);
             if (ctx->packet) {
+                uint8_t nw_ttl = ctx->flow.nw_ttl;
                 flow_extract_l3_onwards(ctx->packet, &ctx->base_flow, eth_type);
                 ctx->inner_flow = ctx->base_flow;
                 flow_copy_l3_onwards(&ctx->flow, &ctx->base_flow);
+                /* If nw_ttl is non-zero then nw_ttl was already set in
+                 * ctx->flow. his can only have occured due to a previous
+                 * copy_ttl_in action so restore the value calculated by
+                 * the action */
+                if (nw_ttl) {
+                    ctx->flow.nw_ttl = nw_ttl;
+                }
             }
         }
     }
@@ -6152,6 +6160,34 @@ compose_dec_ttl(struct action_xlate_ctx *ctx, struct ofpact_cnt_ids *ids)
 }
 
 static bool
+execute_copy_ttl_in_action(struct action_xlate_ctx *ctx)
+{
+    uint8_t nw_ttl;
+
+    if (!eth_type_mpls(ctx->flow.dl_type)) {
+        /* Copying TTL from IP is not supported */
+        return true;
+    }
+
+    if (ctx->flow.mpls_depth > 1) {
+        /* Copying TTL from MPLS to MPLS is not supported */
+        return true;
+    } else {
+        /* MPLS -> IP */
+        nw_ttl = mpls_lse_to_ttl(ctx->flow.mpls_lse);
+    }
+
+    /* Treat a resulting TTL of zero as a stop condition */
+    if (!nw_ttl) {
+        execute_controller_action(ctx, UINT16_MAX, OFPR_INVALID_TTL, 0);
+        return true;
+    }
+
+    ctx->flow.nw_ttl = nw_ttl;
+    return false;
+}
+
+static bool
 execute_copy_ttl_out_action(struct action_xlate_ctx *ctx)
 {
     uint8_t ttl;
@@ -6558,6 +6594,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_COPY_TTL_IN:
+            if (execute_copy_ttl_in_action(ctx)) {
+                goto out;
+            }
+            break;
+
         case OFPACT_COPY_TTL_OUT:
             if (execute_copy_ttl_out_action(ctx)) {
                 goto out;
diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at
index b845072..70e25a6 100644
--- a/tests/ofproto-dpif.at
+++ b/tests/ofproto-dpif.at
@@ -240,6 +240,7 @@ cookie=0xa dl_src=40:44:44:44:44:48 actions=push_mpls:0x8847,load:10->OXM_OF_MPL
 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=0xd dl_src=60:66:66:66:66:67 actions=copy_ttl_in,dec_ttl,pop_mpls:0x0800,dec_ttl,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
 ])
 AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
@@ -513,6 +514,25 @@ NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=56 in_port=1 (via action) data_len
 tcp,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=60:66:66:66:66:66,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64 tcp_csum:0
 ])
 
+dnl Modified MPLS pop 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=60:66:66:66:66:67,dst=50:54:00:00:00:07),eth_type(0x8847),mpls(label=10,tc=3,ttl=100,bos=1),encap(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=0xd total_len=56 in_port=1 (via action) data_len=56 (unbuffered)
+tcp,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=60:66:66:66:66:67,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=99 tcp_csum:0
+dnl
+NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=56 in_port=1 (via action) data_len=56 (unbuffered)
+tcp,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=60:66:66:66:66:67,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=99 tcp_csum:0
+dnl
+NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=56 in_port=1 (via action) data_len=56 (unbuffered)
+tcp,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=60:66:66:66:66:67,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=99 tcp_csum:0
+])
+
 dnl Checksum TCP.
 AT_CHECK([ovs-ofctl monitor br0 65534 -P nxm --detach --no-chdir --pidfile 2> ofctl_monitor.log])
 
@@ -608,6 +628,7 @@ AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
  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
+ cookie=0xd, n_packets=3, n_bytes=180, dl_src=60:66:66:66:66:67 actions=copy_ttl_in,dec_ttl(0),pop_mpls:0x0800,dec_ttl(0),CONTROLLER:65535
  n_packets=3, n_bytes=180, dl_src=10:11:11:11:11:11 actions=CONTROLLER:65535
 NXST_FLOW reply:
 ])
diff --git a/utilities/ovs-ofctl.8.in b/utilities/ovs-ofctl.8.in
index a800996..d564d40 100644
--- a/utilities/ovs-ofctl.8.in
+++ b/utilities/ovs-ofctl.8.in
@@ -1031,6 +1031,11 @@ 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 \fBcopy_ttl_in\fR
+Copy the TTL from the outermost header to next-to-outermost with TTL.
+The implementation supports copying to a next-to-outermost IP header
+from an outermost MPLS header.
+.
 .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
-- 
1.7.10.4




More information about the dev mailing list