svn commit: r267000 - projects/vxlan/sys/net

Bryan Venteicher bryanv at FreeBSD.org
Tue Jun 3 04:38:13 UTC 2014


Author: bryanv
Date: Tue Jun  3 04:38:13 2014
New Revision: 267000
URL: http://svnweb.freebsd.org/changeset/base/267000

Log:
  Misc vxlan changes:
  
   - Fix assert when the multicast interface is detached: the socket
     will have already left the multicast group by the time our event
     handler is called.
   - Use the UDP tunnel callback context from the previous commit.
   - Unlock the INP during our receive handling. The locking could be
     reduced a bit more with some changes to udp_append().

Modified:
  projects/vxlan/sys/net/if_vxlan.c

Modified: projects/vxlan/sys/net/if_vxlan.c
==============================================================================
--- projects/vxlan/sys/net/if_vxlan.c	Tue Jun  3 04:31:42 2014	(r266999)
+++ projects/vxlan/sys/net/if_vxlan.c	Tue Jun  3 04:38:13 2014	(r267000)
@@ -276,6 +276,7 @@ static int	vxlan_setup_multicast_interfa
 
 static int	vxlan_setup_multicast(struct vxlan_softc *);
 static int	vxlan_setup_socket(struct vxlan_softc *);
+static void	vxlan_setup_interface(struct vxlan_softc *);
 static int	vxlan_valid_init_config(struct vxlan_softc *);
 static void	vxlan_init_wait(struct vxlan_softc *);
 static void	vxlan_init_complete(struct vxlan_softc *);
@@ -320,7 +321,7 @@ static int	vxlan_encap6(struct vxlan_sof
 static int	vxlan_transmit(struct ifnet *, struct mbuf *);
 static void	vxlan_qflush(struct ifnet *);
 static void	vxlan_rcv_udp_packet(struct mbuf *, int, struct inpcb *,
-		    const struct sockaddr *);
+		    const struct sockaddr *, void *);
 static int	vxlan_input(struct vxlan_socket *, uint32_t, struct mbuf **,
 		    const struct sockaddr *);
 
@@ -834,7 +835,6 @@ static void
 vxlan_socket_destroy(struct vxlan_socket *vso)
 {
 	struct socket *so;
-	struct inpcb *inp;
 	struct vxlan_socket_mc_info *mc;
 	int i;
 
@@ -854,9 +854,6 @@ vxlan_socket_destroy(struct vxlan_socket
 	so = vso->vxlso_sock;
 	if (so != NULL) {
 		vso->vxlso_sock = NULL;
-		inp = sotoinpcb(so);
-		MPASS(inp->inp_pspare[0] == vso);
-		inp->inp_pspare[0] = NULL;
 		soclose(so);
 	}
 
@@ -909,7 +906,6 @@ vxlan_socket_insert(struct vxlan_socket 
 static int
 vxlan_socket_init(struct vxlan_socket *vso, struct ifnet *ifp)
 {
-	struct inpcb *inp;
 	struct thread *td;
 	int error;
 
@@ -922,16 +918,8 @@ vxlan_socket_init(struct vxlan_socket *v
 		return (error);
 	}
 
-	inp = sotoinpcb(vso->vxlso_sock);
-	/*
-	 * XXX: Use a spare field in the inpcb to obtain the vxlan socket
-	 * in the tunneling callback. We instead should be able to pass a
-	 * context to the tunneling callback.
-	 */
-	MPASS(inp->inp_pspare[0] == NULL);
-	inp->inp_pspare[0] = vso;
-
-	error = udp_set_kernel_tunneling(vso->vxlso_sock, vxlan_rcv_udp_packet);
+	error = udp_set_kernel_tunneling(vso->vxlso_sock,
+	    vxlan_rcv_udp_packet, vso);
 	if (error) {
 		if_printf(ifp, "cannot set tunneling function: %d\n", error);
 		return (error);
@@ -1274,7 +1262,7 @@ vxlan_socket_mc_release_group_by_idx(str
 {
 	union vxlan_sockaddr group, source;
 	struct vxlan_socket_mc_info *mc;
-	int ifidx, leave, error;
+	int ifidx, leave;
 
 	KASSERT(idx >= 0 && idx < VXLAN_SO_MC_MAX_GROUPS,
 	    ("%s: vso %p idx %d out of bounds", __func__, vso, idx));
@@ -1294,9 +1282,12 @@ vxlan_socket_mc_release_group_by_idx(str
 	VXLAN_SO_WUNLOCK(vso);
 
 	if (leave != 0) {
-		error = vxlan_socket_mc_leave_group(vso, &group, &source,
-		    ifidx);
-		MPASS(error == 0);
+		/*
+		 * Our socket's membership in this group may have already
+		 * been removed if we joined through an interface that's
+		 * been detached.
+		 */
+		vxlan_socket_mc_leave_group(vso, &group, &source, ifidx);
 	}
 }
 
@@ -1540,6 +1531,20 @@ out:
 	return (error);
 }
 
+static void
+vxlan_setup_interface(struct vxlan_softc *sc)
+{
+	struct ifnet *ifp;
+
+	ifp = sc->vxl_ifp;
+	ifp->if_hdrlen = ETHER_HDR_LEN + sizeof(struct vxlanudphdr);
+
+	if (VXLAN_SOCKADDR_IS_IPV4(&sc->vxl_dst_addr) != 0)
+		ifp->if_hdrlen += sizeof(struct ip);
+	else if (VXLAN_SOCKADDR_IS_IPV6(&sc->vxl_dst_addr) != 0)
+		ifp->if_hdrlen += sizeof(struct ip6_hdr);
+}
+
 static int
 vxlan_valid_init_config(struct vxlan_softc *sc)
 {
@@ -1594,7 +1599,6 @@ vxlan_valid_init_config(struct vxlan_sof
 
 fail:
 	if_printf(sc->vxl_ifp, "cannot initialize interface: %s\n", reason);
-
 	return (EINVAL);
 }
 
@@ -1638,9 +1642,12 @@ vxlan_init(void *xsc)
 	if (vxlan_valid_init_config(sc) != 0)
 		goto out;
 
+	vxlan_setup_interface(sc);
+
 	if (vxlan_setup_socket(sc) != 0)
 		goto out;
 
+	/* Initialize the default forwarding entry. */
 	vxlan_ftable_entry_init(sc, &sc->vxl_default_fe, empty_mac,
 	    &sc->vxl_dst_addr.sa, VXLAN_FE_FLAG_STATIC);
 
@@ -1652,7 +1659,6 @@ vxlan_init(void *xsc)
 
 out:
 	vxlan_init_complete(sc);
-
 }
 
 static void
@@ -1853,7 +1859,7 @@ vxlan_ctrl_set_local_addr(struct vxlan_s
 	cmd = arg;
 	vxlsa = &cmd->vxlcmd_sa;
 
-	if (!VXLAN_SOCKADDR_IS_IPV4(vxlsa) && !VXLAN_SOCKADDR_IS_IPV6(vxlsa))
+	if (!VXLAN_SOCKADDR_IS_IPV46(vxlsa))
 		return (EINVAL);
 	if (vxlan_sockaddr_in_multicast(vxlsa) != 0)
 		return (EINVAL);
@@ -1879,7 +1885,7 @@ vxlan_ctrl_set_remote_addr(struct vxlan_
 	cmd = arg;
 	vxlsa = &cmd->vxlcmd_sa;
 
-	if (!VXLAN_SOCKADDR_IS_IPV4(vxlsa) && !VXLAN_SOCKADDR_IS_IPV6(vxlsa))
+	if (!VXLAN_SOCKADDR_IS_IPV46(vxlsa))
 		return (EINVAL);
 
 	VXLAN_WLOCK(sc);
@@ -2071,7 +2077,7 @@ vxlan_ctrl_ftable_entry_add(struct vxlan
 	cmd = arg;
 	vxlsa = cmd->vxlcmd_sa;
 
-	if (!VXLAN_SOCKADDR_IS_IPV4(&vxlsa) && !VXLAN_SOCKADDR_IS_IPV6(&vxlsa))
+	if (!VXLAN_SOCKADDR_IS_IPV46(&vxlsa))
 		return (EINVAL);
 	if (vxlan_sockaddr_in_any(&vxlsa) != 0)
 		return (EINVAL);
@@ -2271,6 +2277,7 @@ static int
 vxlan_encap4(struct vxlan_softc *sc, const union vxlan_sockaddr *fvxlsa,
     struct mbuf *m)
 {
+#ifdef INET
 	struct ifnet *ifp;
 	struct ip *ip;
 	struct in_addr srcaddr, dstaddr;
@@ -2316,12 +2323,17 @@ vxlan_encap4(struct vxlan_softc *sc, con
 		ifp->if_oerrors++;
 
 	return (error);
+#else
+	m_freem(m);
+	return (ENOTSUP);
+#endif
 }
 
 static int
 vxlan_encap6(struct vxlan_softc *sc, const union vxlan_sockaddr *fvxlsa,
     struct mbuf *m)
 {
+#ifdef INET6
 	struct ifnet *ifp;
 	struct ip6_hdr *ip6;
 	const struct in6_addr *srcaddr, *dstaddr;
@@ -2366,6 +2378,10 @@ vxlan_encap6(struct vxlan_softc *sc, con
 		ifp->if_oerrors++;
 
 	return (error);
+#else
+	m_freem(m);
+	return (ENOTSUP);
+#endif
 }
 
 static int
@@ -2424,18 +2440,17 @@ vxlan_qflush(struct ifnet *ifp __unused)
 
 static void
 vxlan_rcv_udp_packet(struct mbuf *m, int offset, struct inpcb *inpcb,
-    const struct sockaddr *srcsa)
+    const struct sockaddr *srcsa, void *xvso)
 {
 	struct vxlan_socket *vso;
 	struct vxlan_header *vxh, vxlanhdr;
 	uint32_t vni;
 	int error;
 
-	vso = inpcb->inp_pspare[0];
-	if (vso == NULL)
-		goto out;
+	INP_RUNLOCK(inpcb);
 
 	M_ASSERTPKTHDR(m);
+	vso = xvso;
 	offset += sizeof(struct udphdr);
 
 	if (m->m_pkthdr.len < offset + sizeof(struct vxlan_header))
@@ -2462,6 +2477,8 @@ vxlan_rcv_udp_packet(struct mbuf *m, int
 out:
 	if (m != NULL)
 		m_freem(m);
+
+	INP_RLOCK(inpcb);
 }
 
 static int
@@ -2655,9 +2672,9 @@ vxlan_clone_create(struct if_clone *ifc,
 
 	vxlan_fakeaddr(sc);
 	ether_ifattach(ifp, sc->vxl_hwaddr);
-	/* Now undo some of the damage... */
+
 	ifp->if_baudrate = 0;
-	ifp->if_hdrlen = sizeof(struct vxlanudphdr); /* + sizeof(struct ip) */
+	ifp->if_hdrlen = 0;
 
 	return (0);
 


More information about the svn-src-projects mailing list