summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorGreg Rose <gvrose8192@gmail.com>2018-05-17 17:46:41 -0700
committerBen Pfaff <blp@ovn.org>2018-05-21 20:33:30 -0700
commit068794b43f0eb879648591f8c9ca9c2e6670989f (patch)
treefcae31d318bb07f2029778daf20d303f6e75867f /lib
parent1c385f497271182eb88afc5a38897c9781b575b3 (diff)
downloadopenvswitch-068794b43f0eb879648591f8c9ca9c2e6670989f.tar.gz
erspan: Add flow-based erspan options
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@gmail.com> Signed-off-by: Ben Pfaff <blp@ovn.org>
Diffstat (limited to 'lib')
-rw-r--r--lib/netdev-native-tnl.c38
-rw-r--r--lib/netdev-vport.c120
-rw-r--r--lib/netdev.h5
3 files changed, 123 insertions, 40 deletions
diff --git a/lib/netdev-native-tnl.c b/lib/netdev-native-tnl.c
index c70811eaf..c97491ed0 100644
--- a/lib/netdev-native-tnl.c
+++ b/lib/netdev-native-tnl.c
@@ -628,6 +628,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. */
@@ -645,7 +646,15 @@ 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);
greh->flags = htons(GRE_SEQ);
ersh->ver = 1;
@@ -654,19 +663,38 @@ netdev_erspan_build_header(const struct netdev *netdev,
put_16aligned_be32(ALIGNED_CAST(ovs_16aligned_be32 *, ersh + 1),
htonl(tnl_cfg->erspan_idx));
+ index = (ovs_be32 *)(ersh + 1);
+
+ 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 = ALIGNED_CAST(struct erspan_md2 *, ersh + 1);
+
greh->protocol = htons(ETH_TYPE_ERSPAN2);
greh->flags = htons(GRE_SEQ);
ersh->ver = 2;
set_sid(ersh, sid);
- struct erspan_md2 *md2 = ALIGNED_CAST(struct erspan_md2 *, ersh + 1);
md2->sgt = 0; /* security group tag */
md2->gra = 0;
put_16aligned_be32(&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 805f130d4..1dae7e031 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 0c74dfebd..71ffdab63 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);