summaryrefslogtreecommitdiff
path: root/sys/net/if_bridge.c
diff options
context:
space:
mode:
authorReyk Floeter <reyk@cvs.openbsd.org>2016-09-03 13:46:58 +0000
committerReyk Floeter <reyk@cvs.openbsd.org>2016-09-03 13:46:58 +0000
commitf25fb3ff1b4179dce1d40d4efd3eb083850caccf (patch)
treecef66f3c3c2d3be0f639eab68f35d4bd0998cb59 /sys/net/if_bridge.c
parent2d375858bb375fb1b514a87b235a60a5151cac17 (diff)
Add support for a multipoint-to-multipoint mode in vxlan(4). In this
mode, vxlan(4) must be configured to accept any virtual network identifier with "vnetid any" and added to a bridge(4) or switch(4). This way the driver will dynamically learn the tunnel endpoints and their vnetids for the responses and can be used to dynamically bridge between VXLANs. It is also being used in combination with switch(4) and the OpenFlow tunnel classifiers. With input from yasuoka@ goda@ OK deraadt@ dlg@
Diffstat (limited to 'sys/net/if_bridge.c')
-rw-r--r--sys/net/if_bridge.c70
1 files changed, 37 insertions, 33 deletions
diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c
index 80c4b7e67ec..1b01b47c295 100644
--- a/sys/net/if_bridge.c
+++ b/sys/net/if_bridge.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_bridge.c,v 1.283 2016/09/02 10:01:36 goda Exp $ */
+/* $OpenBSD: if_bridge.c,v 1.284 2016/09/03 13:46:57 reyk Exp $ */
/*
* Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net)
@@ -715,6 +715,7 @@ bridge_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *sa,
struct bridge_rtnode *dst_p = NULL;
struct ether_addr *dst;
struct bridge_softc *sc;
+ struct bridge_tunneltag *brtag;
int error;
/* ifp must be a member interface of the bridge. */
@@ -811,9 +812,15 @@ bridge_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *sa,
}
sendunicast:
- if (dst_p != NULL && dst_p->brt_tunnel.sa.sa_family != AF_UNSPEC &&
- (sa = bridge_tunneltag(m, dst_p->brt_tunnel.sa.sa_family)) != NULL)
- memcpy(sa, &dst_p->brt_tunnel.sa, dst_p->brt_tunnel.sa.sa_len);
+ if ((dst_p != NULL) &&
+ (dst_p->brt_tunnel.brtag_dst.sa.sa_family != AF_UNSPEC) &&
+ ((brtag = bridge_tunneltag(m)) != NULL)) {
+ memcpy(&brtag->brtag_src, &dst_p->brt_tunnel.brtag_src.sa,
+ dst_p->brt_tunnel.brtag_src.sa.sa_len);
+ memcpy(&brtag->brtag_dst, &dst_p->brt_tunnel.brtag_dst.sa,
+ dst_p->brt_tunnel.brtag_dst.sa.sa_len);
+ brtag->brtag_id = dst_p->brt_tunnel.brtag_id;
+ }
bridge_span(sc, m);
if ((dst_if->if_flags & IFF_RUNNING) == 0) {
@@ -1942,7 +1949,7 @@ bridge_send_icmp_err(struct bridge_softc *sc, struct ifnet *ifp,
m_freem(n);
}
-struct sockaddr *
+struct bridge_tunneltag *
bridge_tunnel(struct mbuf *m)
{
struct m_tag *mtag;
@@ -1950,41 +1957,24 @@ bridge_tunnel(struct mbuf *m)
if ((mtag = m_tag_find(m, PACKET_TAG_TUNNEL, NULL)) == NULL)
return (NULL);
- return ((struct sockaddr *)(mtag + 1));
+ return ((struct bridge_tunneltag *)(mtag + 1));
}
-struct sockaddr *
-bridge_tunneltag(struct mbuf *m, int af)
+struct bridge_tunneltag *
+bridge_tunneltag(struct mbuf *m)
{
- struct m_tag *mtag;
- size_t len;
- struct sockaddr *sa;
-
- if ((mtag = m_tag_find(m, PACKET_TAG_TUNNEL, NULL)) != NULL) {
- sa = (struct sockaddr *)(mtag + 1);
- if (sa->sa_family != af) {
- m_tag_delete(m, mtag);
- mtag = NULL;
- }
- }
- if (mtag == NULL) {
- if (af == AF_INET)
- len = sizeof(struct sockaddr_in);
- else if (af == AF_INET6)
- len = sizeof(struct sockaddr_in6);
- else
- return (NULL);
- mtag = m_tag_get(PACKET_TAG_TUNNEL, len, M_NOWAIT);
+ struct m_tag *mtag;
+
+ if ((mtag = m_tag_find(m, PACKET_TAG_TUNNEL, NULL)) == NULL) {
+ mtag = m_tag_get(PACKET_TAG_TUNNEL,
+ sizeof(struct bridge_tunneltag), M_NOWAIT);
if (mtag == NULL)
return (NULL);
- bzero(mtag + 1, len);
- sa = (struct sockaddr *)(mtag + 1);
- sa->sa_family = af;
- sa->sa_len = len;
+ bzero(mtag + 1, sizeof(struct bridge_tunneltag));
m_tag_prepend(m, mtag);
}
- return ((struct sockaddr *)(mtag + 1));
+ return ((struct bridge_tunneltag *)(mtag + 1));
}
void
@@ -2000,6 +1990,20 @@ bridge_copyaddr(struct sockaddr *src, struct sockaddr *dst)
{
if (src != NULL && src->sa_family != AF_UNSPEC)
memcpy(dst, src, src->sa_len);
- else
+ else {
dst->sa_family = AF_UNSPEC;
+ dst->sa_len = 0;
+ }
+}
+
+void
+bridge_copytag(struct bridge_tunneltag *src, struct bridge_tunneltag *dst)
+{
+ if (src == NULL) {
+ memset(dst, 0, sizeof(*dst));
+ } else {
+ bridge_copyaddr(&src->brtag_src.sa, &dst->brtag_src.sa);
+ bridge_copyaddr(&src->brtag_dst.sa, &dst->brtag_dst.sa);
+ dst->brtag_id = src->brtag_id;
+ }
}