summaryrefslogtreecommitdiff
path: root/lib/tnl-ports.c
diff options
context:
space:
mode:
authorPravin B Shelar <pshelar@ovn.org>2016-05-17 17:35:33 -0700
committerPravin B Shelar <pshelar@ovn.org>2016-05-18 19:39:18 -0700
commit98e3f58e8982829c0dc582043f8bf193cd1875d6 (patch)
tree62a9b0075aff110aed91a971a3a863c7cc1067aa /lib/tnl-ports.c
parent1bc3f0ed2615aa2475e4c92339253a6092746ad4 (diff)
downloadopenvswitch-98e3f58e8982829c0dc582043f8bf193cd1875d6.tar.gz
tnl-ports: Handle STT ports.
STT uses TCP port so we need to filter traffic on basis of TCP port numbers. Signed-off-by: Pravin B Shelar <pshelar@ovn.org> Acked-by: Jesse Gross <jesse@kernel.org>
Diffstat (limited to 'lib/tnl-ports.c')
-rw-r--r--lib/tnl-ports.c82
1 files changed, 54 insertions, 28 deletions
diff --git a/lib/tnl-ports.c b/lib/tnl-ports.c
index f399d04d0..e8d43f0f1 100644
--- a/lib/tnl-ports.c
+++ b/lib/tnl-ports.c
@@ -51,7 +51,8 @@ static struct ovs_list addr_list;
struct tnl_port {
odp_port_t port;
- ovs_be16 udp_port;
+ ovs_be16 tp_port;
+ uint8_t nw_proto;
char dev_name[IFNAMSIZ];
struct ovs_list node;
};
@@ -82,7 +83,7 @@ tnl_port_free(struct tnl_port_in *p)
static void
tnl_port_init_flow(struct flow *flow, struct eth_addr mac,
- struct in6_addr *addr, ovs_be16 udp_port)
+ struct in6_addr *addr, uint8_t nw_proto, ovs_be16 tp_port)
{
memset(flow, 0, sizeof *flow);
@@ -95,24 +96,20 @@ tnl_port_init_flow(struct flow *flow, struct eth_addr mac,
flow->ipv6_dst = *addr;
}
- if (udp_port) {
- flow->nw_proto = IPPROTO_UDP;
- } else {
- flow->nw_proto = IPPROTO_GRE;
- }
- flow->tp_dst = udp_port;
+ flow->nw_proto = nw_proto;
+ flow->tp_dst = tp_port;
}
static void
map_insert(odp_port_t port, struct eth_addr mac, struct in6_addr *addr,
- ovs_be16 udp_port, const char dev_name[])
+ uint8_t nw_proto, ovs_be16 tp_port, const char dev_name[])
{
const struct cls_rule *cr;
struct tnl_port_in *p;
struct match match;
memset(&match, 0, sizeof match);
- tnl_port_init_flow(&match.flow, mac, addr, udp_port);
+ tnl_port_init_flow(&match.flow, mac, addr, nw_proto, tp_port);
do {
cr = classifier_lookup(&cls, CLS_MAX_VERSION, &match.flow, NULL);
@@ -129,9 +126,9 @@ map_insert(odp_port_t port, struct eth_addr mac, struct in6_addr *addr,
/* XXX: No fragments support. */
match.wc.masks.nw_frag = FLOW_NW_FRAG_MASK;
- /* 'udp_port' is zero for non-UDP tunnels (e.g. GRE). In this case it
+ /* 'tp_port' is zero for GRE tunnels. In this case it
* doesn't make sense to match on UDP port numbers. */
- if (udp_port) {
+ if (tp_port) {
match.wc.masks.tp_dst = OVS_BE16_MAX;
}
if (IN6_IS_ADDR_V4MAPPED(addr)) {
@@ -152,40 +149,65 @@ map_insert(odp_port_t port, struct eth_addr mac, struct in6_addr *addr,
static void
map_insert_ipdev__(struct ip_device *ip_dev, char dev_name[],
- odp_port_t port, ovs_be16 udp_port)
+ odp_port_t port, uint8_t nw_proto, ovs_be16 tp_port)
{
if (ip_dev->n_addr) {
int i;
for (i = 0; i < ip_dev->n_addr; i++) {
map_insert(port, ip_dev->mac, &ip_dev->addr[i],
- udp_port, dev_name);
+ nw_proto, tp_port, dev_name);
}
}
}
+static uint8_t
+tnl_type_to_nw_proto(const char type[])
+{
+ if (!strcmp(type, "geneve")) {
+ return IPPROTO_UDP;
+ }
+ if (!strcmp(type, "stt")) {
+ return IPPROTO_TCP;
+ }
+ if (!strcmp(type, "gre")) {
+ return IPPROTO_GRE;
+ }
+ if (!strcmp(type, "vxlan")) {
+ return IPPROTO_UDP;
+ }
+ return 0;
+}
+
void
-tnl_port_map_insert(odp_port_t port,
- ovs_be16 udp_port, const char dev_name[])
+tnl_port_map_insert(odp_port_t port, ovs_be16 tp_port,
+ const char dev_name[], const char type[])
{
struct tnl_port *p;
struct ip_device *ip_dev;
+ uint8_t nw_proto;
+
+ nw_proto = tnl_type_to_nw_proto(type);
+ if (!nw_proto) {
+ return;
+ }
ovs_mutex_lock(&mutex);
LIST_FOR_EACH(p, node, &port_list) {
- if (udp_port == p->udp_port) {
+ if (tp_port == p->tp_port && p->nw_proto == nw_proto) {
goto out;
}
}
p = xzalloc(sizeof *p);
p->port = port;
- p->udp_port = udp_port;
+ p->tp_port = tp_port;
+ p->nw_proto = nw_proto;
ovs_strlcpy(p->dev_name, dev_name, sizeof p->dev_name);
ovs_list_insert(&port_list, &p->node);
LIST_FOR_EACH(ip_dev, node, &addr_list) {
- map_insert_ipdev__(ip_dev, p->dev_name, p->port, p->udp_port);
+ map_insert_ipdev__(ip_dev, p->dev_name, p->port, p->nw_proto, p->tp_port);
}
out:
@@ -205,39 +227,43 @@ tnl_port_unref(const struct cls_rule *cr)
}
static void
-map_delete(struct eth_addr mac, struct in6_addr *addr, ovs_be16 udp_port)
+map_delete(struct eth_addr mac, struct in6_addr *addr,
+ ovs_be16 tp_port, uint8_t nw_proto)
{
const struct cls_rule *cr;
struct flow flow;
- tnl_port_init_flow(&flow, mac, addr, udp_port);
+ tnl_port_init_flow(&flow, mac, addr, nw_proto, tp_port);
cr = classifier_lookup(&cls, CLS_MAX_VERSION, &flow, NULL);
tnl_port_unref(cr);
}
static void
-ipdev_map_delete(struct ip_device *ip_dev, ovs_be16 udp_port)
+ipdev_map_delete(struct ip_device *ip_dev, ovs_be16 tp_port, uint8_t nw_proto)
{
if (ip_dev->n_addr) {
int i;
for (i = 0; i < ip_dev->n_addr; i++) {
- map_delete(ip_dev->mac, &ip_dev->addr[i], udp_port);
+ map_delete(ip_dev->mac, &ip_dev->addr[i], tp_port, nw_proto);
}
}
}
void
-tnl_port_map_delete(ovs_be16 udp_port)
+tnl_port_map_delete(ovs_be16 tp_port, const char type[])
{
struct tnl_port *p, *next;
struct ip_device *ip_dev;
bool found = false;
+ uint8_t nw_proto;
+
+ nw_proto = tnl_type_to_nw_proto(type);
ovs_mutex_lock(&mutex);
LIST_FOR_EACH_SAFE(p, next, node, &port_list) {
- if (p->udp_port == udp_port) {
+ if (p->tp_port == tp_port && p->nw_proto == nw_proto) {
ovs_list_remove(&p->node);
found = true;
break;
@@ -248,7 +274,7 @@ tnl_port_map_delete(ovs_be16 udp_port)
goto out;
}
LIST_FOR_EACH(ip_dev, node, &addr_list) {
- ipdev_map_delete(ip_dev, p->udp_port);
+ ipdev_map_delete(ip_dev, p->tp_port, p->nw_proto);
}
free(p);
@@ -343,7 +369,7 @@ map_insert_ipdev(struct ip_device *ip_dev)
struct tnl_port *p;
LIST_FOR_EACH(p, node, &port_list) {
- map_insert_ipdev__(ip_dev, p->dev_name, p->port, p->udp_port);
+ map_insert_ipdev__(ip_dev, p->dev_name, p->port, p->nw_proto, p->tp_port);
}
}
@@ -409,7 +435,7 @@ delete_ipdev(struct ip_device *ip_dev)
struct tnl_port *p;
LIST_FOR_EACH(p, node, &port_list) {
- ipdev_map_delete(ip_dev, p->udp_port);
+ ipdev_map_delete(ip_dev, p->tp_port, p->nw_proto);
}
ovs_list_remove(&ip_dev->node);