[ovs-dev] [PATCH 10/16] Add support for copy_ttl_in action

Simon Horman horms at verge.net.au
Fri Jan 25 07:22:16 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.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        |   24 ++++++++++++++++++++++--
 tests/ofproto-dpif.at         |   21 +++++++++++++++++++++
 utilities/ovs-ofctl.8.in      |    5 +++++
 10 files changed, 84 insertions(+), 4 deletions(-)

diff --git a/include/openflow/nicira-ext.h b/include/openflow/nicira-ext.h
index c592410..780618a 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 a87099a..2e3fb28 100644
--- a/lib/match.c
+++ b/lib/match.c
@@ -995,7 +995,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 eb8e1b7..f850832 100644
--- a/lib/ofp-actions.c
+++ b/lib/ofp-actions.c
@@ -412,6 +412,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;
@@ -806,6 +810,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;
@@ -1170,6 +1178,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:
@@ -1424,6 +1433,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;
@@ -1608,6 +1621,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:
@@ -1744,6 +1758,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;
@@ -1902,6 +1920,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:
@@ -2129,6 +2148,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 4ca21da..7690468 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 af7a88f..f656feb 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_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 1a9ca0e..43c414f 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 e4dc514..b85960c 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")
@@ -67,6 +68,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 e9945fd..fa64723 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -5959,10 +5959,26 @@ compose_dec_ttl(struct action_xlate_ctx *ctx, struct ofpact_cnt_ids *ids)
 }
 
 static void
+execute_copy_ttl_in_action(struct action_xlate_ctx *ctx)
+{
+    if (!eth_type_mpls(ctx->flow.dl_type)) {
+        /* Copying TTL from IP is not supported */
+        return;
+    }
+
+    if (ctx->flow.mpls_depth > 1) {
+        /* Copying TTL from MPLS to MPLS is not supported */
+        return;
+    } else {
+        /* MPLS -> IP */
+        ctx->flow.nw_ttl = mpls_lse_to_ttl(ctx->flow.mpls_lse);
+    }
+}
+
+static void
 execute_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)) {
+    if (!eth_type_mpls(ctx->flow.dl_type)) {
         /* Copying TTL to IP is not supported */
         return;
     }
@@ -6376,6 +6392,10 @@ 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:
+            execute_copy_ttl_in_action(ctx);
+            break;
+
         case OFPACT_COPY_TTL_OUT:
             execute_copy_ttl_out_action(ctx);
             break;
diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at
index 7f3a504..7a4caaf 100644
--- a/tests/ofproto-dpif.at
+++ b/tests/ofproto-dpif.at
@@ -259,6 +259,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])
@@ -532,6 +533,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),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])
 
@@ -627,6 +647,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 29c07c4..6434643 100644
--- a/utilities/ovs-ofctl.8.in
+++ b/utilities/ovs-ofctl.8.in
@@ -1023,6 +1023,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