diff --git a/sbin/ifconfig/ifconfig.8 b/sbin/ifconfig/ifconfig.8 --- a/sbin/ifconfig/ifconfig.8 +++ b/sbin/ifconfig/ifconfig.8 @@ -399,9 +399,10 @@ A FIB .Ar fib_number is assigned to all packets encapsulated by tunnel interface, e.g., -.Xr gif 4 +.Xr gif 4 , +.Xr gre 4 and -.Xr gre 4 . +.Xr vxlan 4 . .It Cm maclabel Ar label If Mandatory Access Control support is enabled in the kernel, set the MAC label to diff --git a/sys/net/if_vxlan.c b/sys/net/if_vxlan.c --- a/sys/net/if_vxlan.c +++ b/sys/net/if_vxlan.c @@ -163,6 +163,7 @@ struct vxlan_softc { struct ifnet *vxl_ifp; int vxl_reqcap; + u_int vxl_fibnum; struct vxlan_socket *vxl_sock; uint32_t vxl_vni; union vxlan_sockaddr vxl_src_addr; @@ -2378,6 +2379,20 @@ VXLAN_WUNLOCK(sc); break; + case SIOCGTUNFIB: + ifr->ifr_fib = sc->vxl_fibnum; + break; + + case SIOCSTUNFIB: + if ((error = priv_check(curthread, PRIV_NET_VXLAN)) != 0) + break; + + if (ifr->ifr_fib >= rt_numfibs) + error = EINVAL; + else + sc->vxl_fibnum = ifr->ifr_fib; + break; + default: error = ether_ioctl(ifp, cmd, data); break; @@ -2533,7 +2548,7 @@ sin->sin_family = AF_INET; sin->sin_len = sizeof(*sin); sin->sin_addr = ip->ip_dst; - ro->ro_nh = fib4_lookup(RT_DEFAULT_FIB, ip->ip_dst, 0, NHR_NONE, + ro->ro_nh = fib4_lookup(M_GETFIB(m), ip->ip_dst, 0, NHR_NONE, 0); if (ro->ro_nh == NULL) { m_freem(m); @@ -2645,7 +2660,7 @@ sin6->sin6_family = AF_INET6; sin6->sin6_len = sizeof(*sin6); sin6->sin6_addr = ip6->ip6_dst; - ro->ro_nh = fib6_lookup(RT_DEFAULT_FIB, &ip6->ip6_dst, 0, + ro->ro_nh = fib6_lookup(M_GETFIB(m), &ip6->ip6_dst, 0, NHR_NONE, 0); if (ro->ro_nh == NULL) { m_freem(m); @@ -2719,6 +2734,7 @@ fe = NULL; mcifp = NULL; + M_SETFIB(m, sc->vxl_fibnum); ETHER_BPF_MTAP(ifp, m); VXLAN_RLOCK(sc, &tracker); @@ -3174,6 +3190,7 @@ sc = malloc(sizeof(struct vxlan_softc), M_VXLAN, M_WAITOK | M_ZERO); sc->vxl_unit = unit; + sc->vxl_fibnum = curthread->td_proc->p_fibnum; vxlan_set_default_config(sc); error = vxlan_stats_alloc(sc); if (error != 0) diff --git a/sys/netinet6/raw_ip6.c b/sys/netinet6/raw_ip6.c --- a/sys/netinet6/raw_ip6.c +++ b/sys/netinet6/raw_ip6.c @@ -352,6 +352,8 @@ void rip6_ctlinput(int cmd, struct sockaddr *sa, void *d) { + struct rm_priotracker in6_ifa_tracker; + struct in6_ifaddr *ia; struct ip6ctlparam *ip6cp = NULL; const struct sockaddr_in6 *sa6_src = NULL; void *cmdarg; @@ -361,6 +363,49 @@ sa->sa_len != sizeof(struct sockaddr_in6)) return; + switch (cmd) { + case PRC_IFDOWN: + IN6_IFADDR_RLOCK(&in6_ifa_tracker); + CK_STAILQ_FOREACH(ia, &V_in6_ifaddrhead, ia_link) { + if (ia->ia_ifa.ifa_addr == sa + && (ia->ia_flags & IFA_ROUTE)) { + ifa_ref(&ia->ia_ifa); + IN6_IFADDR_RUNLOCK(&in6_ifa_tracker); + /* + * TODO: kills the interface route. + */ + // in6_scrubprefix(...); + ifa_free(&ia->ia_ifa); + break; + + } + } + if (ia == NULL) + IN6_IFADDR_RUNLOCK(&in6_ifa_tracker); + return; + + case PRC_IFUP: + IN6_IFADDR_RLOCK(&in6_ifa_tracker); + CK_STAILQ_FOREACH(ia, &V_in6_ifaddrhead, ia_link) { + if (ia->ia_ifa.ifa_addr == sa) + break; + } + if (ia == NULL || (ia->ia_flags & IFA_ROUTE)) { + IN6_IFADDR_RUNLOCK(&in6_ifa_tracker); + return; + } + ifa_ref(&ia->ia_ifa); + IN6_IFADDR_RUNLOCK(&in6_ifa_tracker); + err = ifa_del_loopback_route((struct ifaddr *)ia, sa); + rt_addrmsg(RTM_ADD, &ia->ia_ifa, ia->ia_ifp->if_fib); + err = in6_handle_ifaddr_route(RTM_ADD, ia); + if (err == 0) + ia->ia_flags |= IFA_ROUTE; + err = ifa_add_loopback_route((struct ifaddr *)ia, sa); + ifa_free(&ia->ia_ifa); + return; + } + if ((unsigned)cmd >= PRC_NCMDS) return; if (PRC_IS_REDIRECT(cmd))