[ovs-dev] [RFC PATCH 09/13] tunneling: ofproto-dpif: prevent IPv6 loops
Jiri Benc
jbenc at redhat.com
Thu May 14 18:12:40 UTC 2015
Store the original IP address similarly to IPv4.
Change the is_tunnel boolean to the outer protocol; null protocol indicates
no tunnel.
Signed-off-by: Jiri Benc <jbenc at redhat.com>
---
ofproto/ofproto-dpif-xlate.c | 27 +++++++++++++++++----------
ofproto/ofproto-dpif-xlate.h | 2 +-
ofproto/ofproto-dpif.c | 28 +++++++++++++++-------------
3 files changed, 33 insertions(+), 24 deletions(-)
diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
index f73787744db3..0307982c9c19 100644
--- a/ofproto/ofproto-dpif-xlate.c
+++ b/ofproto/ofproto-dpif-xlate.c
@@ -159,7 +159,8 @@ struct xport {
struct hmap skb_priorities; /* Map of 'skb_priority_to_dscp's. */
bool may_enable; /* May be enabled in bonds. */
- bool is_tunnel; /* Is a tunnel port. */
+ uint16_t tunnel_protocol; /* Tunnel underlying protocol.
+ * 0 when not a tunnel port. */
struct cfm *cfm; /* CFM handle or null. */
struct bfd *bfd; /* BFD handle or null. */
@@ -182,6 +183,7 @@ struct xlate_ctx {
* if a tunnel is marked as 'ip_remote=flow', and the flow does not
* actually set the tun_dst field. */
ovs_be32 orig_tunnel_ip_dst;
+ struct in6_addr orig_tunnel_ipv6_dst;
/* Stack for the push and pop actions. Each stack element is of type
* "union mf_subvalue". */
@@ -506,7 +508,8 @@ static void xlate_xport_set(struct xport *xport, odp_port_t odp_port,
const struct bfd *bfd, const struct lldp *lldp,
int stp_port_no, const struct rstp_port *rstp_port,
enum ofputil_port_config config,
- enum ofputil_port_state state, bool is_tunnel,
+ enum ofputil_port_state state,
+ uint16_t tunnel_protocol,
bool may_enable);
static void xlate_xbridge_remove(struct xlate_cfg *, struct xbridge *);
static void xlate_xbundle_remove(struct xlate_cfg *, struct xbundle *);
@@ -649,12 +652,12 @@ xlate_xport_set(struct xport *xport, odp_port_t odp_port,
const struct bfd *bfd, const struct lldp *lldp, int stp_port_no,
const struct rstp_port* rstp_port,
enum ofputil_port_config config, enum ofputil_port_state state,
- bool is_tunnel, bool may_enable)
+ uint16_t tunnel_protocol, bool may_enable)
{
xport->config = config;
xport->state = state;
xport->stp_port_no = stp_port_no;
- xport->is_tunnel = is_tunnel;
+ xport->tunnel_protocol = tunnel_protocol;
xport->may_enable = may_enable;
xport->odp_port = odp_port;
@@ -747,7 +750,7 @@ xlate_xport_copy(struct xbridge *xbridge, struct xbundle *xbundle,
xlate_xport_set(new_xport, xport->odp_port, xport->netdev, xport->cfm,
xport->bfd, xport->lldp, xport->stp_port_no,
xport->rstp_port, xport->config, xport->state,
- xport->is_tunnel, xport->may_enable);
+ xport->tunnel_protocol, xport->may_enable);
if (xport->peer) {
struct xport *peer = xport_lookup(new_xcfg, xport->peer->ofport);
@@ -987,7 +990,7 @@ xlate_ofport_set(struct ofproto_dpif *ofproto, struct ofbundle *ofbundle,
int stp_port_no, const struct rstp_port *rstp_port,
const struct ofproto_port_queue *qdscp_list, size_t n_qdscp,
enum ofputil_port_config config,
- enum ofputil_port_state state, bool is_tunnel,
+ enum ofputil_port_state state, uint16_t tunnel_protocol,
bool may_enable)
{
size_t i;
@@ -1008,7 +1011,7 @@ xlate_ofport_set(struct ofproto_dpif *ofproto, struct ofbundle *ofbundle,
ovs_assert(xport->ofp_port == ofp_port);
xlate_xport_set(xport, odp_port, netdev, cfm, bfd, lldp,
- stp_port_no, rstp_port, config, state, is_tunnel,
+ stp_port_no, rstp_port, config, state, tunnel_protocol,
may_enable);
if (xport->peer) {
@@ -2904,7 +2907,7 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port,
}
}
- if (xport->is_tunnel) {
+ if (xport->tunnel_protocol) {
/* Save tunnel metadata so that changes made due to
* the Logical (tunnel) Port are not visible for any further
* matches, while explicit set actions on tunnel metadata are.
@@ -2915,7 +2918,10 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port,
xlate_report(ctx, "Tunneling decided against output");
goto out; /* restore flow_nw_tos */
}
- if (flow->tunnel.ip_dst == ctx->orig_tunnel_ip_dst) {
+ if ((xport->tunnel_protocol == ETH_TYPE_IP &&
+ flow->tunnel.ip_dst == ctx->orig_tunnel_ip_dst) ||
+ (xport->tunnel_protocol == ETH_TYPE_IPV6 &&
+ ipv6_addr_equals(&flow->tunnel.ipv6_dst, &ctx->orig_tunnel_ipv6_dst))) {
xlate_report(ctx, "Not tunneling to our own address");
goto out; /* restore flow_nw_tos */
}
@@ -4734,6 +4740,7 @@ xlate_actions(struct xlate_in *xin, struct xlate_out *xout)
ctx.base_flow = *flow;
memset(&ctx.base_flow.tunnel, 0, sizeof ctx.base_flow.tunnel);
ctx.orig_tunnel_ip_dst = flow->tunnel.ip_dst;
+ ctx.orig_tunnel_ipv6_dst = flow->tunnel.ipv6_dst;
if (!xin->skip_wildcards) {
wc = &xout->wc;
@@ -4893,7 +4900,7 @@ xlate_actions(struct xlate_in *xin, struct xlate_out *xout)
}
/* Tunnel stats only for non-recirculated packets. */
- if (!xin->recirc && in_port && in_port->is_tunnel) {
+ if (!xin->recirc && in_port && in_port->tunnel_protocol) {
if (ctx.xin->resubmit_stats) {
netdev_vport_inc_rx(in_port->netdev, ctx.xin->resubmit_stats);
if (in_port->bfd) {
diff --git a/ofproto/ofproto-dpif-xlate.h b/ofproto/ofproto-dpif-xlate.h
index 6c8ade308c77..84b9a02cc295 100644
--- a/ofproto/ofproto-dpif-xlate.h
+++ b/ofproto/ofproto-dpif-xlate.h
@@ -231,7 +231,7 @@ void xlate_ofport_set(struct ofproto_dpif *, struct ofbundle *,
int stp_port_no, const struct rstp_port *rstp_port,
const struct ofproto_port_queue *qdscp,
size_t n_qdscp, enum ofputil_port_config,
- enum ofputil_port_state, bool is_tunnel,
+ enum ofputil_port_state, uint16_t tunnel_protocol,
bool may_enable);
void xlate_ofport_remove(struct ofport_dpif *);
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index bf893214b524..1d17761134cb 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -164,8 +164,8 @@ struct ofport_dpif {
struct cfm *cfm; /* Connectivity Fault Management, if any. */
struct bfd *bfd; /* BFD, if any. */
struct lldp *lldp; /* lldp, if any. */
+ uint16_t tunnel_protocol; /* Tunnel underlaying protocol or 0. */
bool may_enable; /* May be enabled in bonds. */
- bool is_tunnel; /* This port is a tunnel. */
bool is_layer3; /* This is a layer 3 port. */
long long int carrier_seq; /* Carrier status changes. */
struct ofport_dpif *peer; /* Peer if patch port. */
@@ -579,7 +579,7 @@ type_run(const char *type)
char namebuf[NETDEV_VPORT_NAME_BUFSIZE];
const char *dp_port;
- if (!iter->is_tunnel) {
+ if (!iter->tunnel_protocol) {
continue;
}
@@ -669,7 +669,7 @@ type_run(const char *type)
ofport->lldp, ofport->peer, stp_port,
ofport->rstp_port, ofport->qdscp,
ofport->n_qdscp, ofport->up.pp.config,
- ofport->up.pp.state, ofport->is_tunnel,
+ ofport->up.pp.state, ofport->tunnel_protocol,
ofport->may_enable);
}
xlate_txn_commit();
@@ -1641,6 +1641,7 @@ port_construct(struct ofport *port_)
struct ofport_dpif *port = ofport_dpif_cast(port_);
struct ofproto_dpif *ofproto = ofproto_dpif_cast(port->up.ofproto);
const struct netdev *netdev = port->up.netdev;
+ const struct netdev_tunnel_config *tnl_cfg;
char namebuf[NETDEV_VPORT_NAME_BUFSIZE];
struct dpif_port dpif_port;
int error;
@@ -1655,7 +1656,7 @@ port_construct(struct ofport *port_)
port->stp_state = STP_DISABLED;
port->rstp_port = NULL;
port->rstp_state = RSTP_DISABLED;
- port->is_tunnel = false;
+ port->tunnel_protocol = 0;
port->peer = NULL;
port->qdscp = NULL;
port->n_qdscp = 0;
@@ -1685,11 +1686,12 @@ port_construct(struct ofport *port_)
port->odp_port = dpif_port.port_no;
- if (netdev_get_tunnel_config(netdev)) {
+ tnl_cfg = netdev_get_tunnel_config(netdev);
+ if (tnl_cfg) {
atomic_count_inc(&ofproto->backer->tnl_count);
tnl_port_add(port, port->up.netdev, port->odp_port,
ovs_native_tunneling_is_on(ofproto), namebuf);
- port->is_tunnel = true;
+ port->tunnel_protocol = tnl_cfg->protocol;
if (ofproto->ipfix) {
dpif_ipfix_add_tunnel_port(ofproto->ipfix, port_, port->odp_port);
}
@@ -1738,7 +1740,7 @@ port_destruct(struct ofport *port_)
* happens when the ofproto is being destroyed, since the caller
* assumes that removal of attached ports will happen as part of
* destruction. */
- if (!port->is_tunnel) {
+ if (!port->tunnel_protocol) {
dpif_port_del(ofproto->backer->dpif, port->odp_port);
}
}
@@ -1748,17 +1750,17 @@ port_destruct(struct ofport *port_)
port->peer = NULL;
}
- if (port->odp_port != ODPP_NONE && !port->is_tunnel) {
+ if (port->odp_port != ODPP_NONE && !port->tunnel_protocol) {
ovs_rwlock_wrlock(&ofproto->backer->odp_to_ofport_lock);
hmap_remove(&ofproto->backer->odp_to_ofport_map, &port->odp_port_node);
ovs_rwlock_unlock(&ofproto->backer->odp_to_ofport_lock);
}
- if (port->is_tunnel) {
+ if (port->tunnel_protocol) {
atomic_count_dec(&ofproto->backer->tnl_count);
}
- if (port->is_tunnel && ofproto->ipfix) {
+ if (port->tunnel_protocol && ofproto->ipfix) {
dpif_ipfix_del_tunnel_port(ofproto->ipfix, port->odp_port);
}
@@ -1804,7 +1806,7 @@ port_modified(struct ofport *port_)
netdev_vport_get_dpif_port(netdev, namebuf, sizeof namebuf);
- if (port->is_tunnel) {
+ if (port->tunnel_protocol) {
struct ofproto_dpif *ofproto = ofproto_dpif_cast(port->up.ofproto);
if (tnl_port_reconfigure(port, netdev, port->odp_port,
@@ -1893,7 +1895,7 @@ set_ipfix(
if (new_di == true) {
struct ofport_dpif *ofport;
HMAP_FOR_EACH (ofport, up.hmap_node, &ofproto->up.ports) {
- if (ofport->is_tunnel == true) {
+ if (ofport->tunnel_protocol) {
dpif_ipfix_add_tunnel_port(di, &ofport->up, ofport->odp_port);
}
}
@@ -3397,7 +3399,7 @@ port_del(struct ofproto *ofproto_, ofp_port_t ofp_port)
sset_find_and_delete(&ofproto->ghost_ports,
netdev_get_name(ofport->up.netdev));
ofproto->backer->need_revalidate = REV_RECONFIGURE;
- if (!ofport->is_tunnel && !netdev_vport_is_patch(ofport->up.netdev)) {
+ if (!ofport->tunnel_protocol && !netdev_vport_is_patch(ofport->up.netdev)) {
error = dpif_port_del(ofproto->backer->dpif, ofport->odp_port);
if (!error) {
/* The caller is going to close ofport->up.netdev. If this is a
--
1.8.3.1
More information about the dev
mailing list