Page MenuHomeFreeBSD

D4111.id10062.diff
No OneTemporary

D4111.id10062.diff

Index: sys/net/if.h
===================================================================
--- sys/net/if.h
+++ sys/net/if.h
@@ -181,6 +181,7 @@
#define LINK_STATE_UNKNOWN 0 /* link invalid/unknown */
#define LINK_STATE_DOWN 1 /* link is down */
#define LINK_STATE_UP 2 /* link is up */
+#define LINK_STATE_UP_FORCE 3 /* link is up force event */
/*
* Some convenience macros used for setting ifi_baudrate.
Index: sys/net/if.c
===================================================================
--- sys/net/if.c
+++ sys/net/if.c
@@ -2028,6 +2028,9 @@
if (ifp->if_link_state == link_state)
return;
+ if (link_state == LINK_STATE_UP_FORCE)
+ link_state = LINK_STATE_UP;
+
ifp->if_link_state = link_state;
taskqueue_enqueue(taskqueue_swi, &ifp->if_linktask);
Index: sys/net/if_lagg.c
===================================================================
--- sys/net/if_lagg.c
+++ sys/net/if_lagg.c
@@ -1775,7 +1775,12 @@
/* Our link is considered up if at least one of our ports is active */
SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) {
if (lp->lp_ifp->if_link_state == LINK_STATE_UP) {
- new_link = LINK_STATE_UP;
+ /*
+ * Force up to ensure ifnet_link_event is generated
+ * allowing IP protocols to notify other nodes of
+ * potential address move.
+ */
+ new_link = LINK_STATE_UP_FORCE;
break;
}
}
@@ -1818,7 +1823,7 @@
LAGG_WUNLOCK(sc);
}
-struct lagg_port *
+static __noinline struct lagg_port *
lagg_link_active(struct lagg_softc *sc, struct lagg_port *lp)
{
struct lagg_port *lp_next, *rval = NULL;
Index: sys/net/if_var.h
===================================================================
--- sys/net/if_var.h
+++ sys/net/if_var.h
@@ -529,6 +529,9 @@
#define IF_LLADDR(ifp) \
LLADDR((struct sockaddr_dl *)((ifp)->if_addr->ifa_addr))
+#define IFA_SINADDR(ifa) \
+ ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr
+
uint64_t if_setbaudrate(if_t ifp, uint64_t baudrate);
uint64_t if_getbaudrate(if_t ifp);
int if_setcapabilities(if_t ifp, int capabilities);
Index: sys/netinet/if_ether.h
===================================================================
--- sys/netinet/if_ether.h
+++ sys/netinet/if_ether.h
@@ -119,6 +119,7 @@
void arprequest(struct ifnet *, const struct in_addr *,
const struct in_addr *, u_char *);
void arp_ifinit(struct ifnet *, struct ifaddr *);
+void arp_announce(struct ifnet *);
void arp_announce_ifaddr(struct ifnet *, struct in_addr addr, u_char *);
#endif
Index: sys/netinet/if_ether.c
===================================================================
--- sys/netinet/if_ether.c
+++ sys/netinet/if_ether.c
@@ -145,6 +145,7 @@
static void arp_iflladdr(void *arg __unused, struct ifnet *ifp);
static eventhandler_tag iflladdr_tag;
+static eventhandler_tag ifnet_link_event_tag;
static const struct netisr_handler arp_nh = {
.nh_name = "arp",
@@ -1158,29 +1159,45 @@
}
/*
- * Sends gratuitous ARPs for each ifaddr to notify other
- * nodes about the address change.
+ * Send gratuitous ARPs for all interfaces addresses to notify other nodes of
+ * changes.
+ *
+ * This is a noop if the interface isn't up or has been flagged for no ARP.
*/
-static __noinline void
-arp_handle_ifllchange(struct ifnet *ifp)
+void
+arp_announce(struct ifnet *ifp)
{
struct ifaddr *ifa;
+ if (!(ifp->if_flags & IFF_UP) || (ifp->if_flags & IFF_NOARP))
+ return;
+
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
if (ifa->ifa_addr->sa_family == AF_INET)
- arp_ifinit(ifp, ifa);
+ arp_announce_ifaddr(ifp, IFA_SINADDR(ifa),
+ IF_LLADDR(ifp));
}
}
/*
- * A handler for interface link layer address change event.
+ * A handler for interface linkstate change events.
+ */
+static void
+arp_ifnet_link_event(void *arg __unused, struct ifnet *ifp, int linkstate)
+{
+
+ if (linkstate == LINK_STATE_UP)
+ arp_announce(ifp);
+}
+
+/*
+ * A handler for interface link layer address change events.
*/
static __noinline void
arp_iflladdr(void *arg __unused, struct ifnet *ifp)
{
- if ((ifp->if_flags & IFF_UP) != 0)
- arp_handle_ifllchange(ifp);
+ arp_announce(ifp);
}
static void
@@ -1188,8 +1205,12 @@
{
netisr_register(&arp_nh);
- if (IS_DEFAULT_VNET(curvnet))
+
+ if (IS_DEFAULT_VNET(curvnet)) {
iflladdr_tag = EVENTHANDLER_REGISTER(iflladdr_event,
arp_iflladdr, NULL, EVENTHANDLER_PRI_ANY);
+ ifnet_link_event_tag = EVENTHANDLER_REGISTER(ifnet_link_event,
+ arp_ifnet_link_event, 0, EVENTHANDLER_PRI_ANY);
+ }
}
SYSINIT(arp, SI_SUB_PROTO_DOMAIN, SI_ORDER_ANY, arp_init, 0);
Index: sys/netinet/ip_carp.c
===================================================================
--- sys/netinet/ip_carp.c
+++ sys/netinet/ip_carp.c
@@ -1009,13 +1009,12 @@
carp_send_arp(struct carp_softc *sc)
{
struct ifaddr *ifa;
- struct in_addr addr;
CARP_FOREACH_IFA(sc, ifa) {
if (ifa->ifa_addr->sa_family != AF_INET)
continue;
- addr = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr;
- arp_announce_ifaddr(sc->sc_carpdev, addr, LLADDR(&sc->sc_addr));
+ arp_announce_ifaddr(sc->sc_carpdev, IFA_SINADDR(ifa),
+ LLADDR(&sc->sc_addr));
}
}
@@ -1037,17 +1036,13 @@
static void
carp_send_na(struct carp_softc *sc)
{
- static struct in6_addr mcast = IN6ADDR_LINKLOCAL_ALLNODES_INIT;
struct ifaddr *ifa;
- struct in6_addr *in6;
CARP_FOREACH_IFA(sc, ifa) {
if (ifa->ifa_addr->sa_family != AF_INET6)
continue;
- in6 = IFA_IN6(ifa);
- nd6_na_output(sc->sc_carpdev, &mcast, in6,
- ND_NA_FLAG_OVERRIDE, 1, NULL);
+ nd6_announce_ifaddr(sc->sc_carpdev, ifa);
DELAY(1000); /* XXX */
}
}
Index: sys/netinet6/in6.c
===================================================================
--- sys/netinet6/in6.c
+++ sys/netinet6/in6.c
@@ -113,7 +113,7 @@
#define V_icmp6_nodeinfo_oldmcprefix VNET(icmp6_nodeinfo_oldmcprefix)
/*
- * Definitions of some costant IP6 addresses.
+ * Definitions of some constant IP6 addresses.
*/
const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
Index: sys/netinet6/nd6.h
===================================================================
--- sys/netinet6/nd6.h
+++ sys/netinet6/nd6.h
@@ -398,6 +398,8 @@
#ifdef VIMAGE
void nd6_destroy(void);
#endif
+void nd6_announce(struct ifnet *);
+void nd6_announce_ifaddr(struct ifnet *, struct ifaddr *);
struct nd_ifinfo *nd6_ifattach(struct ifnet *);
void nd6_ifdetach(struct nd_ifinfo *);
int nd6_is_addr_neighbor(const struct sockaddr_in6 *, struct ifnet *);
Index: sys/netinet6/nd6.c
===================================================================
--- sys/netinet6/nd6.c
+++ sys/netinet6/nd6.c
@@ -112,6 +112,7 @@
#endif
static eventhandler_tag lle_event_eh;
+static eventhandler_tag ifnet_link_event_eh;
/* for debugging? */
#if 0
@@ -196,6 +197,46 @@
type == RTM_ADD ? RTF_UP: 0), 0, RT_DEFAULT_FIB);
}
+static void
+nd6_ifnet_link_event(void *arg __unused, struct ifnet *ifp, int linkstate)
+{
+
+ if (linkstate == LINK_STATE_UP)
+ nd6_announce(ifp);
+}
+
+/*
+ * Send unsolicited neighbor advertisements for all interface addresses to
+ * notify other nodes of changes.
+ *
+ * This is a noop if the interface isn't up.
+ */
+void
+nd6_announce(struct ifnet *ifp)
+{
+ struct ifaddr *ifa;
+
+ if (!(ifp->if_flags & IFF_UP))
+ return;
+
+ TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
+ if (ifa->ifa_addr->sa_family == AF_INET6)
+ nd6_announce_ifaddr(ifp, ifa);
+ }
+}
+
+/*
+ * Send neighbor advertisement to notify other nodes of changes.
+ */
+void
+nd6_announce_ifaddr(struct ifnet *ifp, struct ifaddr *ifa)
+{
+
+ nd6_na_output(ifp, &in6addr_linklocal_allnodes, IFA_IN6(ifa),
+ (((struct in6_ifaddr *)ifa)->ia6_flags &
+ IN6_IFF_ANYCAST) ? 0 : ND_NA_FLAG_OVERRIDE, 1, NULL);
+}
+
void
nd6_init(void)
{
@@ -211,9 +252,12 @@
nd6_slowtimo, curvnet);
nd6_dad_init();
- if (IS_DEFAULT_VNET(curvnet))
+ if (IS_DEFAULT_VNET(curvnet)) {
lle_event_eh = EVENTHANDLER_REGISTER(lle_event, nd6_lle_event,
NULL, EVENTHANDLER_PRI_ANY);
+ ifnet_link_event_eh = EVENTHANDLER_REGISTER(ifnet_link_event,
+ nd6_ifnet_link_event, NULL, EVENTHANDLER_PRI_ANY);
+ }
}
#ifdef VIMAGE
@@ -223,8 +267,10 @@
callout_drain(&V_nd6_slowtimo_ch);
callout_drain(&V_nd6_timer_ch);
- if (IS_DEFAULT_VNET(curvnet))
+ if (IS_DEFAULT_VNET(curvnet)) {
EVENTHANDLER_DEREGISTER(lle_event, lle_event_eh);
+ EVENTHANDLER_DEREGISTER(ifnet_link_event, ifnet_link_event_eh);
+ }
}
#endif

File Metadata

Mime Type
text/plain
Expires
Fri, Jun 12, 7:58 AM (9 h, 20 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33902721
Default Alt Text
D4111.id10062.diff (8 KB)

Event Timeline