[ovs-dev] [PATCH 30/41] erspan: Add flow-based erspan options

Greg Rose gvrose8192 at gmail.com
Thu May 17 21:15:22 UTC 2018


From: William Tu <u9012063 at gmail.com>

The patch add supports for flow-based erspan options.
The erspan_ver, erspan_idx, erspan_dir, and erspan_hwid can be
set as "flow" so that its value is set by the openflow rule,
instead of statically configured at port creation time.

Signed-off-by: William Tu <u9012063 at gmail.com>
---
 lib/match.c              |   8 ++--
 lib/netdev-native-tnl.c  |  32 +++++++++++--
 lib/netdev-vport.c       | 120 +++++++++++++++++++++++++++++++++--------------
 lib/netdev.h             |   5 ++
 ofproto/tunnel.c         |  11 +++--
 tests/tunnel-push-pop.at |  35 +++++++++++++-
 tests/tunnel.at          |  68 +++++++++++++++++++++++----
 7 files changed, 221 insertions(+), 58 deletions(-)

diff --git a/lib/match.c b/lib/match.c
index f1b450c..5305dbd 100644
--- a/lib/match.c
+++ b/lib/match.c
@@ -1288,16 +1288,16 @@ format_flow_tunnel(struct ds *s, const struct match *match)
         ds_put_format(s, "tun_ttl=%"PRIu8",", tnl->ip_ttl);
     }
     if (wc->masks.tunnel.erspan_ver) {
-        ds_put_format(s, "erspan_ver=%"PRIu8",", tnl->erspan_ver);
+        ds_put_format(s, "tun_erspan_ver=%"PRIu8",", tnl->erspan_ver);
     }
     if (wc->masks.tunnel.erspan_idx && tnl->erspan_ver == 1) {
-        ds_put_format(s, "erspan_idx=%#"PRIx32",", tnl->erspan_idx);
+        ds_put_format(s, "tun_erspan_idx=%#"PRIx32",", tnl->erspan_idx);
     }
     if (wc->masks.tunnel.erspan_dir && tnl->erspan_ver == 2) {
-        ds_put_format(s, "erspan_dir=%"PRIu8",", tnl->erspan_dir);
+        ds_put_format(s, "tun_erspan_dir=%"PRIu8",", tnl->erspan_dir);
     }
     if (wc->masks.tunnel.erspan_hwid && tnl->erspan_ver == 2) {
-        ds_put_format(s, "erspan_hwid=%#"PRIx8",", tnl->erspan_hwid);
+        ds_put_format(s, "tun_erspan_hwid=%#"PRIx8",", tnl->erspan_hwid);
     }
     if (wc->masks.tunnel.flags & FLOW_TNL_F_MASK) {
         format_flags_masked(s, "tun_flags", flow_tun_flag_to_string,
diff --git a/lib/netdev-native-tnl.c b/lib/netdev-native-tnl.c
index fe36ea9..4966cd3 100644
--- a/lib/netdev-native-tnl.c
+++ b/lib/netdev-native-tnl.c
@@ -630,6 +630,7 @@ netdev_erspan_build_header(const struct netdev *netdev,
     struct erspan_base_hdr *ersh;
     unsigned int hlen;
     uint32_t tun_id;
+    int erspan_ver;
     uint16_t sid;
 
     /* XXX: RCUfy tnl_cfg. */
@@ -647,7 +648,13 @@ netdev_erspan_build_header(const struct netdev *netdev,
         sid = (uint16_t) tun_id;
     }
 
-    if (tnl_cfg->erspan_ver == 1) {
+    if (tnl_cfg->erspan_ver_flow) {
+        erspan_ver = params->flow->tunnel.erspan_ver;
+    } else {
+        erspan_ver = tnl_cfg->erspan_ver;
+    }
+
+    if (erspan_ver == 1) {
         ovs_be32 *index;
 
         greh->protocol = htons(ETH_TYPE_ERSPAN1);
@@ -656,10 +663,15 @@ netdev_erspan_build_header(const struct netdev *netdev,
         set_sid(ersh, sid);
 
         index = (ovs_be32 *)(ersh + 1);
-        *index = htonl(tnl_cfg->erspan_idx);
+
+        if (tnl_cfg->erspan_idx_flow) {
+            *index = htonl(params->flow->tunnel.erspan_idx);
+        } else {
+            *index = htonl(tnl_cfg->erspan_idx);
+        }
 
         hlen = ERSPAN_GREHDR_LEN + sizeof *ersh + ERSPAN_V1_MDSIZE;
-    } else if (tnl_cfg->erspan_ver == 2) {
+    } else if (erspan_ver == 2) {
         struct erspan_md2 *md2;
 
         greh->protocol = htons(ETH_TYPE_ERSPAN2);
@@ -671,8 +683,18 @@ netdev_erspan_build_header(const struct netdev *netdev,
         md2->sgt = 0; /* security group tag */
         md2->gra = 0;
         md2->timestamp = 0;
-        set_hwid(md2, tnl_cfg->erspan_hwid);
-        md2->dir = tnl_cfg->erspan_dir;
+
+        if (tnl_cfg->erspan_hwid_flow) {
+            set_hwid(md2, params->flow->tunnel.erspan_hwid);
+        } else {
+            set_hwid(md2, tnl_cfg->erspan_hwid);
+        }
+
+        if (tnl_cfg->erspan_dir_flow) {
+            md2->dir = params->flow->tunnel.erspan_dir;
+        } else {
+            md2->dir = tnl_cfg->erspan_dir;
+        }
 
         hlen = ERSPAN_GREHDR_LEN + sizeof *ersh + ERSPAN_V2_MDSIZE;
     } else {
diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c
index 805f130..1dae7e0 100644
--- a/lib/netdev-vport.c
+++ b/lib/netdev-vport.c
@@ -545,36 +545,63 @@ set_tunnel_config(struct netdev *dev_, const struct smap *args, char **errp)
             tnl_cfg.egress_pkt_mark = strtoul(node->value, NULL, 10);
             tnl_cfg.set_egress_pkt_mark = true;
         } else if (!strcmp(node->key, "erspan_idx")) {
-            tnl_cfg.erspan_idx = strtol(node->value, NULL, 16);
-            if (tnl_cfg.erspan_idx & ~ERSPAN_IDX_MASK) {
-                ds_put_format(&errors, "%s: invalid erspan index: %s\n",
-                              name, node->value);
-                err = EINVAL;
-                goto out;
+            if (!strcmp(node->value, "flow")) {
+                tnl_cfg.erspan_idx_flow = true;
+            } else {
+                tnl_cfg.erspan_idx_flow = false;
+                tnl_cfg.erspan_idx = strtol(node->value, NULL, 16);
+
+                if (tnl_cfg.erspan_idx & ~ERSPAN_IDX_MASK) {
+                    ds_put_format(&errors, "%s: invalid erspan index: %s\n",
+                                  name, node->value);
+                    err = EINVAL;
+                    goto out;
+                }
             }
         } else if (!strcmp(node->key, "erspan_ver")) {
-            tnl_cfg.erspan_ver = atoi(node->value);
-            if (tnl_cfg.erspan_ver != 1 && tnl_cfg.erspan_ver != 2) {
-                ds_put_format(&errors, "%s: invalid erspan version: %s\n",
-                              name, node->value);
-                err = EINVAL;
-                goto out;
+            if (!strcmp(node->value, "flow")) {
+                tnl_cfg.erspan_ver_flow = true;
+                tnl_cfg.erspan_idx_flow = true;
+                tnl_cfg.erspan_dir_flow = true;
+                tnl_cfg.erspan_hwid_flow = true;
+            } else {
+                tnl_cfg.erspan_ver_flow = false;
+                tnl_cfg.erspan_ver = atoi(node->value);
+
+                if (tnl_cfg.erspan_ver != 1 && tnl_cfg.erspan_ver != 2) {
+                    ds_put_format(&errors, "%s: invalid erspan version: %s\n",
+                                  name, node->value);
+                    err = EINVAL;
+                    goto out;
+                }
             }
         } else if (!strcmp(node->key, "erspan_dir")) {
-            tnl_cfg.erspan_dir = atoi(node->value);
-            if (tnl_cfg.erspan_dir != 0 && tnl_cfg.erspan_dir != 1) {
-                ds_put_format(&errors, "%s: invalid erspan direction: %s\n",
-                              name, node->value);
-                err = EINVAL;
-                goto out;
+            if (!strcmp(node->value, "flow")) {
+                tnl_cfg.erspan_dir_flow = true;
+            } else {
+                tnl_cfg.erspan_dir_flow = false;
+                tnl_cfg.erspan_dir = atoi(node->value);
+
+                if (tnl_cfg.erspan_dir != 0 && tnl_cfg.erspan_dir != 1) {
+                    ds_put_format(&errors, "%s: invalid erspan direction: %s\n",
+                                  name, node->value);
+                    err = EINVAL;
+                    goto out;
+                }
             }
         } else if (!strcmp(node->key, "erspan_hwid")) {
-            tnl_cfg.erspan_hwid = strtol(node->value, NULL, 16);
-            if (tnl_cfg.erspan_hwid & ~(ERSPAN_HWID_MASK >> 4)) {
-                ds_put_format(&errors, "%s: invalid erspan hardware ID: %s\n",
-                              name, node->value);
-                err = EINVAL;
-                goto out;
+            if (!strcmp(node->value, "flow")) {
+                tnl_cfg.erspan_hwid_flow = true;
+            } else {
+                tnl_cfg.erspan_hwid_flow = false;
+                tnl_cfg.erspan_hwid = strtol(node->value, NULL, 16);
+
+                if (tnl_cfg.erspan_hwid & ~(ERSPAN_HWID_MASK >> 4)) {
+                    ds_put_format(&errors, "%s: invalid erspan hardware ID: %s\n",
+                                  name, node->value);
+                    err = EINVAL;
+                    goto out;
+                }
             }
         } else {
             ds_put_format(&errors, "%s: unknown %s argument '%s'\n", name,
@@ -767,17 +794,40 @@ get_tunnel_config(const struct netdev *dev, struct smap *args)
                         "%"PRIu32, tnl_cfg.egress_pkt_mark);
     }
 
-    if (tnl_cfg.erspan_idx) {
-        smap_add_format(args, "erspan_idx", "0x%x", tnl_cfg.erspan_idx);
-    }
-    if (tnl_cfg.erspan_ver) {
-        smap_add_format(args, "erspan_ver", "%d", tnl_cfg.erspan_ver);
-    }
-    if (tnl_cfg.erspan_dir) {
-        smap_add_format(args, "erspan_dir", "%d", tnl_cfg.erspan_dir);
-    }
-    if (tnl_cfg.erspan_hwid) {
-        smap_add_format(args, "erspan_hwid", "0x%x", tnl_cfg.erspan_hwid);
+    if (!strcmp("erspan", type) || !strcmp("ip6erspan", type)) {
+        if (tnl_cfg.erspan_ver_flow) {
+            /* since version number is not determined,
+             * assume print all other as flow
+             */
+            smap_add(args, "erspan_ver", "flow");
+            smap_add(args, "erspan_idx", "flow");
+            smap_add(args, "erspan_dir", "flow");
+            smap_add(args, "erspan_hwid", "flow");
+        } else {
+            smap_add_format(args, "erspan_ver", "%d", tnl_cfg.erspan_ver);
+
+            if (tnl_cfg.erspan_ver == 1) {
+                if (tnl_cfg.erspan_idx_flow) {
+                    smap_add(args, "erspan_idx", "flow");
+                } else {
+                    smap_add_format(args, "erspan_idx", "0x%x",
+                                    tnl_cfg.erspan_idx);
+                }
+            } else if (tnl_cfg.erspan_ver == 2) {
+                if (tnl_cfg.erspan_dir_flow) {
+                    smap_add(args, "erspan_dir", "flow");
+                } else {
+                    smap_add_format(args, "erspan_dir", "%d",
+                                    tnl_cfg.erspan_dir);
+                }
+                if (tnl_cfg.erspan_hwid_flow) {
+                    smap_add(args, "erspan_hwid", "flow");
+                } else {
+                    smap_add_format(args, "erspan_hwid", "0x%x",
+                                    tnl_cfg.erspan_hwid);
+                }
+            }
+        }
     }
 
     return 0;
diff --git a/lib/netdev.h b/lib/netdev.h
index 0c74dfe..71ffdab 100644
--- a/lib/netdev.h
+++ b/lib/netdev.h
@@ -134,6 +134,11 @@ struct netdev_tunnel_config {
     uint8_t erspan_ver;
     uint8_t erspan_dir;
     uint8_t erspan_hwid;
+
+    bool erspan_ver_flow;
+    bool erspan_idx_flow;
+    bool erspan_dir_flow;
+    bool erspan_hwid_flow;
 };
 
 void netdev_run(void);
diff --git a/ofproto/tunnel.c b/ofproto/tunnel.c
index 2fd6ffb..03f0ab7 100644
--- a/ofproto/tunnel.c
+++ b/ofproto/tunnel.c
@@ -474,16 +474,19 @@ tnl_port_send(const struct ofport_dpif *ofport, struct flow *flow,
         wc->masks.pkt_mark = UINT32_MAX;
     }
 
-    if (cfg->erspan_ver) {
+    if (!cfg->erspan_ver_flow) {
         flow->tunnel.erspan_ver = cfg->erspan_ver;
     }
-    if (cfg->erspan_idx) {
+
+    if (!cfg->erspan_idx_flow) {
         flow->tunnel.erspan_idx = cfg->erspan_idx;
     }
-    if (cfg->erspan_dir) {
+
+    if (!cfg->erspan_dir_flow) {
         flow->tunnel.erspan_dir = cfg->erspan_dir;
     }
-    if (cfg->erspan_hwid) {
+
+    if (!cfg->erspan_hwid_flow) {
         flow->tunnel.erspan_hwid = cfg->erspan_hwid;
     }
 
diff --git a/tests/tunnel-push-pop.at b/tests/tunnel-push-pop.at
index 1a181f3..8f2529c 100644
--- a/tests/tunnel-push-pop.at
+++ b/tests/tunnel-push-pop.at
@@ -9,6 +9,12 @@ AT_CHECK([ovs-vsctl add-port int-br t1 -- set Interface t1 type=erspan \
                     -- add-port int-br t2 -- set Interface t2 type=erspan \
                        options:remote_ip=1.1.2.92 options:key=567 options:erspan_ver=2 \
                        options:erspan_dir=1 options:erspan_hwid=0x7 ofport_request=3\
+                    -- add-port int-br t3 -- set Interface t3 type=erspan \
+                       options:remote_ip=flow options:erspan_ver=2 options:key=456 \
+                       options:erspan_hwid=flow options:erspan_dir=flow ofport_request=4\
+                    -- add-port int-br t4 -- set Interface t4 type=erspan \
+                       options:remote_ip=flow options:erspan_ver=2 options:key=56 \
+                       options:erspan_ver=flow ofport_request=5\
                        ], [0])
 
 AT_CHECK([ovs-appctl dpif/show], [0], [dnl
@@ -20,6 +26,8 @@ dummy at ovs-dummy: hit:0 missed:0
 		int-br 65534/2: (dummy-internal)
 		t1 2/3: (erspan: erspan_idx=0x3, erspan_ver=1, key=123, remote_ip=1.1.2.92)
 		t2 3/3: (erspan: erspan_dir=1, erspan_hwid=0x7, erspan_ver=2, key=567, remote_ip=1.1.2.92)
+		t3 4/3: (erspan: erspan_dir=flow, erspan_hwid=flow, erspan_ver=2, key=456, remote_ip=flow)
+		t4 5/3: (erspan: erspan_dir=flow, erspan_hwid=flow, erspan_idx=flow, erspan_ver=flow, key=56, remote_ip=flow)
 ])
 
 dnl First setup dummy interface IP address, then add the route
@@ -66,7 +74,7 @@ AT_CHECK([ovs-appctl tnl/neigh/show | tail -n+3 | sort], [0], [dnl
 
 AT_CHECK([ovs-appctl tnl/ports/show |sort], [0], [dnl
 Listening ports:
-erspan_sys (3) ref_cnt=2
+erspan_sys (3) ref_cnt=4
 ])
 
 dnl Check ERSPAN v1 tunnel push
@@ -85,6 +93,31 @@ AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: tnl_push(tnl_port(3),header(size=54,type=107,eth(dst=f8:bc:12:44:34:b6,src=aa:55:aa:55:00:00,dl_type=0x0800),ipv4(src=1.1.2.88,dst=1.1.2.92,proto=47,tos=0,ttl=64,frag=0x4000),erspan(ver=2,sid=0x237,dir=1,hwid=0x7)),out_port(100))
 ])
 
+dnl Check ERSPAN v2 flow-based tunnel push
+AT_CHECK([ovs-ofctl mod-flows int-br "action=set_field:1.1.2.94->tun_dst,set_field:1->tun_erspan_dir,set_field:0x1->tun_erspan_hwid,4"])
+AT_CHECK([ovs-appctl revalidator/wait])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:00),eth_type(0x0800),ipv4(src=1.1.3.88,dst=1.1.3.112,proto=47,tos=0,ttl=64,frag=no)'], [0], [stdout])
+AT_CHECK([tail -1 stdout], [0],
+  [Datapath actions: tnl_push(tnl_port(3),header(size=54,type=107,eth(dst=f8:bc:12:44:34:b8,src=aa:55:aa:55:00:00,dl_type=0x0800),ipv4(src=1.1.2.88,dst=1.1.2.94,proto=47,tos=0,ttl=64,frag=0x4000),erspan(ver=2,sid=0x1c8,dir=1,hwid=0x1)),out_port(100))
+])
+
+dnl Check ERSPAN v2 flow-based tunnel push, erspan_ver=flow
+dnl Dynamically set erspan v2
+AT_CHECK([ovs-ofctl mod-flows int-br "action=set_field:1.1.2.94->tun_dst,set_field:2->tun_erspan_ver,set_field:1->tun_erspan_dir,set_field:0x1->tun_erspan_hwid,5"])
+AT_CHECK([ovs-appctl revalidator/wait])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:00),eth_type(0x0800),ipv4(src=1.1.3.88,dst=1.1.3.112,proto=47,tos=0,ttl=64,frag=no)'], [0], [stdout])
+AT_CHECK([tail -1 stdout], [0],
+  [Datapath actions: tnl_push(tnl_port(3),header(size=54,type=107,eth(dst=f8:bc:12:44:34:b8,src=aa:55:aa:55:00:00,dl_type=0x0800),ipv4(src=1.1.2.88,dst=1.1.2.94,proto=47,tos=0,ttl=64,frag=0x4000),erspan(ver=2,sid=0x38,dir=1,hwid=0x1)),out_port(100))
+])
+
+dnl Dynamically set erspan v1
+AT_CHECK([ovs-ofctl mod-flows int-br "action=set_field:1.1.2.94->tun_dst,set_field:1->tun_erspan_ver,set_field:1->tun_erspan_idx,5"])
+AT_CHECK([ovs-appctl revalidator/wait])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:00),eth_type(0x0800),ipv4(src=1.1.3.88,dst=1.1.3.112,proto=47,tos=0,ttl=64,frag=no)'], [0], [stdout])
+AT_CHECK([tail -1 stdout], [0],
+  [Datapath actions: tnl_push(tnl_port(3),header(size=50,type=107,eth(dst=f8:bc:12:44:34:b8,src=aa:55:aa:55:00:00,dl_type=0x0800),ipv4(src=1.1.2.88,dst=1.1.2.94,proto=47,tos=0,ttl=64,frag=0x4000),erspan(ver=1,sid=0x38,idx=0x1)),out_port(100))
+])
+
 dnl Check ERSPAN tunnel pop
 AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:00),eth_type(0x0800),ipv4(src=1.1.11.93,dst=1.1.2.88,proto=47,tos=0,ttl=64,frag=no)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
diff --git a/tests/tunnel.at b/tests/tunnel.at
index 315453d..2bc004c 100644
--- a/tests/tunnel.at
+++ b/tests/tunnel.at
@@ -408,11 +408,42 @@ AT_CLEANUP
 
 AT_SETUP([tunnel - ERSPAN])
 OVS_VSWITCHD_START([add-port br0 p1 -- set Interface p1 type=erspan \
-                    options:remote_ip=1.1.1.1 ofport_request=1])
+                    options:remote_ip=1.1.1.1 options:key=1 options:erspan_ver=1 \
+                    options:erspan_idx=0x0 ofport_request=1 \
+                 -- add-port br0 p2 -- set Interface p2 type=erspan \
+                    options:remote_ip=1.1.1.1 ofport_request=2 \
+                    options:key=flow options:erspan_ver=1 options:erspan_idx=flow \
+                 -- add-port br0 p3 -- set Interface p3 type=erspan \
+                    options:remote_ip=1.1.1.1 ofport_request=3 \
+                    options:key=10 options:erspan_ver=2 options:erspan_dir=flow \
+                    options:erspan_hwid=flow \
+                 -- add-port br0 p4 -- set Interface p4 type=erspan \
+                    options:remote_ip=1.2.3.4 ofport_request=4 \
+                    options:key=flow options:erspan_ver=flow\
+                 ])
 
 AT_CHECK([ovs-appctl dpif/show | tail -n +3], [0], [dnl
 		br0 65534/100: (dummy-internal)
-		p1 1/1: (erspan: remote_ip=1.1.1.1)
+		p1 1/1: (erspan: erspan_idx=0x0, erspan_ver=1, key=1, remote_ip=1.1.1.1)
+		p2 2/1: (erspan: erspan_idx=flow, erspan_ver=1, key=flow, remote_ip=1.1.1.1)
+		p3 3/1: (erspan: erspan_dir=flow, erspan_hwid=flow, erspan_ver=2, key=10, remote_ip=1.1.1.1)
+		p4 4/1: (erspan: erspan_dir=flow, erspan_hwid=flow, erspan_idx=flow, erspan_ver=flow, key=flow, remote_ip=1.2.3.4)
+])
+
+dnl Check ERSPAN v1 flow-based tunnel push
+AT_CHECK([ovs-ofctl add-flow br0 "in_port=1, actions=set_tunnel:11,set_field:0x1->tun_erspan_idx,2"])
+
+dnl Check ERSPAN v2 flow-based tunnel push
+AT_CHECK([ovs-ofctl add-flow br0 "in_port=2, actions=set_field:1->tun_erspan_dir,set_field:0x0->tun_erspan_hwid,3"])
+
+AT_CHECK([ovs-ofctl add-flow br0 "in_port=3, actions=set_field:2->tun_erspan_ver,set_field:1->tun_erspan_dir,set_field:0x0->tun_erspan_hwid,4"])
+
+AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip],
+[0], [dnl
+NXST_FLOW reply:
+ in_port=1 actions=set_tunnel:0xb,set_field:0x1->tun_erspan_idx,output:2
+ in_port=2 actions=set_field:1->tun_erspan_dir,set_field:0->tun_erspan_hwid,output:3
+ in_port=3 actions=set_field:2->tun_erspan_ver,set_field:1->tun_erspan_dir,set_field:0->tun_erspan_hwid,output:4
 ])
 
 OVS_VSWITCHD_STOP
@@ -523,28 +554,28 @@ AT_CHECK([tail -1 stdout], [0],
 dnl receive packet from ERSPAN port with v1 metadata
 AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'recirc_id(0),tunnel(tun_id=0x1,src=1.1.1.1,dst=2.2.2.2,ttl=64,erspan(ver=1,idx=0x7),flags(df|key)),in_port(1),skb_mark(0),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(frag=no)'], [0], [stdout])
 AT_CHECK([tail -2 stdout], [0],
-  [Megaflow: recirc_id=0,eth,ip,tun_id=0x1,tun_src=1.1.1.1,tun_dst=2.2.2.2,tun_tos=0,erspan_ver=1,erspan_idx=0x7,tun_flags=+df-csum+key,in_port=3,nw_frag=no
+  [Megaflow: recirc_id=0,eth,ip,tun_id=0x1,tun_src=1.1.1.1,tun_dst=2.2.2.2,tun_tos=0,tun_erspan_ver=1,tun_erspan_idx=0x7,tun_flags=+df-csum+key,in_port=3,nw_frag=no
 Datapath actions: 3
 ])
 
 dnl receive packet from ERSPAN port with wrong v1 metadata
 AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'recirc_id(0),tunnel(tun_id=0x1,src=1.1.1.1,dst=2.2.2.2,ttl=64,erspan(ver=1,idx=0xabcd),flags(df|key)),in_port(1),skb_mark(0),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(frag=no)'], [0], [stdout])
 AT_CHECK([tail -2 stdout], [0],
-  [Megaflow: recirc_id=0,eth,ip,tun_id=0x1,tun_src=1.1.1.1,tun_dst=2.2.2.2,tun_tos=0,erspan_ver=1,erspan_idx=0xabcd,tun_flags=+df-csum+key,in_port=3,nw_frag=no
+  [Megaflow: recirc_id=0,eth,ip,tun_id=0x1,tun_src=1.1.1.1,tun_dst=2.2.2.2,tun_tos=0,tun_erspan_ver=1,tun_erspan_idx=0xabcd,tun_flags=+df-csum+key,in_port=3,nw_frag=no
 Datapath actions: drop
 ])
 
 dnl receive packet from ERSPAN port with v2 metadata
 AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'recirc_id(0),tunnel(tun_id=0x2,src=1.1.1.2,dst=2.2.2.2,ttl=64,erspan(ver=2,dir=1,hwid=0x7),flags(df|key)),in_port(1),skb_mark(0),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(frag=no)'], [0], [stdout])
 AT_CHECK([tail -2 stdout], [0],
-  [Megaflow: recirc_id=0,eth,ip,tun_id=0x2,tun_src=1.1.1.2,tun_dst=2.2.2.2,tun_tos=0,erspan_ver=2,erspan_dir=1,erspan_hwid=0x1,tun_flags=+df-csum+key,in_port=4,nw_frag=no
+  [Megaflow: recirc_id=0,eth,ip,tun_id=0x2,tun_src=1.1.1.2,tun_dst=2.2.2.2,tun_tos=0,tun_erspan_ver=2,tun_erspan_dir=1,tun_erspan_hwid=0x1,tun_flags=+df-csum+key,in_port=4,nw_frag=no
 Datapath actions: 2
 ])
 
 dnl receive packet from ERSPAN port with wrong v2 metadata
 AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'recirc_id(0),tunnel(tun_id=0x2,src=1.1.1.2,dst=2.2.2.2,ttl=64,erspan(ver=2,dir=0,hwid=0x17),flags(df|key)),in_port(1),skb_mark(0),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(frag=no)'], [0], [stdout])
 AT_CHECK([tail -2 stdout], [0],
-  [Megaflow: recirc_id=0,eth,ip,tun_id=0x2,tun_src=1.1.1.2,tun_dst=2.2.2.2,tun_tos=0,erspan_ver=2,erspan_dir=0,erspan_hwid=0x1,tun_flags=+df-csum+key,in_port=4,nw_frag=no
+  [Megaflow: recirc_id=0,eth,ip,tun_id=0x2,tun_src=1.1.1.2,tun_dst=2.2.2.2,tun_tos=0,tun_erspan_ver=2,tun_erspan_dir=0,tun_erspan_hwid=0x1,tun_flags=+df-csum+key,in_port=4,nw_frag=no
 Datapath actions: drop
 ])
 
@@ -557,17 +588,36 @@ AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip],
 NXST_FLOW reply:
  in_port=1 actions=output:3
  in_port=2 actions=output:4
- erspan_ver=1,erspan_idx=0x7,in_port=3 actions=output:1
- erspan_ver=2,in_port=4 actions=output:2
+ tun_erspan_ver=1,tun_erspan_idx=0x7,in_port=3 actions=output:1
+ tun_erspan_ver=2,in_port=4 actions=output:2
 ])
 
 dnl this time it won't drop
 AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'recirc_id(0),tunnel(tun_id=0x2,src=1.1.1.2,dst=2.2.2.2,ttl=64,erspan(ver=2,dir=0,hwid=0x17),flags(df|key)),in_port(1),skb_mark(0),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(frag=no)'], [0], [stdout])
 AT_CHECK([tail -2 stdout], [0],
-  [Megaflow: recirc_id=0,eth,ip,tun_id=0x2,tun_src=1.1.1.2,tun_dst=2.2.2.2,tun_tos=0,erspan_ver=2,tun_flags=+df-csum+key,in_port=4,nw_frag=no
+  [Megaflow: recirc_id=0,eth,ip,tun_id=0x2,tun_src=1.1.1.2,tun_dst=2.2.2.2,tun_tos=0,tun_erspan_ver=2,tun_flags=+df-csum+key,in_port=4,nw_frag=no
 Datapath actions: 2
 ])
 
+dnl flow-based erspan_idx options
+AT_CHECK([ovs-vsctl add-port br0 p5 -- set Interface p5 type=erspan \
+          options:remote_ip=1.1.1.2 ofport_request=5 \
+          options:key=flow options:erspan_ver=1 options:erspan_idx=flow])
+
+AT_CHECK([ovs-ofctl del-flows br0])
+AT_CHECK([ovs-ofctl add-flow br0 "in_port=1, actions=set_tunnel:11,set_field:0x7->tun_erspan_idx,5"])
+
+AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip],
+[0], [dnl
+NXST_FLOW reply:
+ in_port=1 actions=set_tunnel:0xb,set_field:0x7->tun_erspan_idx,output:5
+])
+
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(3),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
+AT_CHECK([tail -1 stdout], [0],
+  [Datapath actions: set(tunnel(tun_id=0xb,dst=1.1.1.2,ttl=64,erspan(ver=1,idx=0x7),flags(df|key))),1
+])
+
 OVS_VSWITCHD_STOP
 AT_CLEANUP
 
-- 
1.8.3.1



More information about the dev mailing list