Date: Sun, 7 Dec 2014 23:08:07 +0000 (UTC) From: "Alexander V. Chernikov" <melifaro@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r275586 - in projects/routing/sys: net netinet netinet6 Message-ID: <201412072308.sB7N87wO084516@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: melifaro Date: Sun Dec 7 23:08:07 2014 New Revision: 275586 URL: https://svnweb.freebsd.org/changeset/base/275586 Log: * Retire abstract llentry_free() in favor of lltable_drop_entry_queue() and explicit calls to RTENTRY_FREE_LOCKED() * Use lltable_prefix_free() in arp_ifscrub to be consistent with nd6. * Rename <lltable_|llt>_delete function to _delete_addr() to note that this function is used to external callers. Make this function maintain its own locking. * Use lookup/unlink/clear call chain from internal callers instead of delete_addr. * Fix LLE_DELETED flag handling Modified: projects/routing/sys/net/if_llatbl.c projects/routing/sys/net/if_llatbl.h projects/routing/sys/netinet/if_ether.c projects/routing/sys/netinet/in.c projects/routing/sys/netinet6/in6.c projects/routing/sys/netinet6/nd6.c Modified: projects/routing/sys/net/if_llatbl.c ============================================================================== --- projects/routing/sys/net/if_llatbl.c Sun Dec 7 22:30:54 2014 (r275585) +++ projects/routing/sys/net/if_llatbl.c Sun Dec 7 23:08:07 2014 (r275586) @@ -189,21 +189,17 @@ llentries_unlink(struct lltable *llt, st } /* - * Deletes an address from the address table. - * This function is called by the timer functions - * such as arptimer() and nd6_llinfo_timer(), and - * the caller does the locking. + * Helper function user to drop all mbufs in hold queue. * * Returns the number of held packets, if any, that were dropped. */ size_t -llentry_free(struct llentry *lle) +lltable_drop_entry_queue(struct llentry *lle) { size_t pkts_dropped; struct mbuf *next; LLE_WLOCK_ASSERT(lle); - KASSERT((lle->la_flags & LLE_LINKED) == 0, ("Freeing linked lle")); pkts_dropped = 0; while ((lle->la_numheld > 0) && (lle->la_hold != NULL)) { @@ -218,8 +214,6 @@ llentry_free(struct llentry *lle) ("%s: la_numheld %d > 0, pkts_droped %zd", __func__, lle->la_numheld, pkts_dropped)); - LLE_FREE_LOCKED(lle); - return (pkts_dropped); } @@ -522,9 +516,7 @@ lla_rt_output(struct rt_msghdr *rtm, str break; case RTM_DELETE: - IF_AFDATA_CFG_WLOCK(ifp); - error = (llt->llt_delete(llt, 0, dst)); - IF_AFDATA_CFG_WUNLOCK(ifp); + error = lltable_delete_addr(llt, 0, dst); return (error == 0 ? 0 : ENOENT); default: Modified: projects/routing/sys/net/if_llatbl.h ============================================================================== --- projects/routing/sys/net/if_llatbl.h Sun Dec 7 22:30:54 2014 (r275585) +++ projects/routing/sys/net/if_llatbl.h Sun Dec 7 23:08:07 2014 (r275586) @@ -151,7 +151,7 @@ typedef struct llentry *(llt_lookup_t)(s const struct sockaddr *l3addr); typedef struct llentry *(llt_create_t)(struct lltable *, u_int flags, const struct sockaddr *l3addr); -typedef int (llt_delete_t)(struct lltable *, u_int flags, +typedef int (llt_delete_addr_t)(struct lltable *, u_int flags, const struct sockaddr *l3addr); typedef int (llt_dump_entry_t)(struct lltable *, struct llentry *, struct sysctl_req *); @@ -175,7 +175,7 @@ struct lltable { llt_lookup_t *llt_lookup; llt_create_t *llt_create; - llt_delete_t *llt_delete; + llt_delete_addr_t *llt_delete_addr; llt_dump_entry_t *llt_dump_entry; llt_hash_t *llt_hash; llt_match_prefix_t *llt_match_prefix; @@ -219,10 +219,12 @@ void lltable_drain(int); #endif int lltable_sysctl_dumparp(int, struct sysctl_req *); -size_t llentry_free(struct llentry *); struct llentry *llentry_alloc(struct ifnet *, struct lltable *, struct sockaddr_storage *); +/* helper functions */ +size_t lltable_drop_entry_queue(struct llentry *); + /* * Generic link layer address lookup function. */ @@ -243,11 +245,11 @@ lltable_create_lle(struct lltable *llt, } static __inline int -lltable_delete_lle(struct lltable *llt, u_int flags, +lltable_delete_addr(struct lltable *llt, u_int flags, const struct sockaddr *l3addr) { - return llt->llt_delete(llt, flags, l3addr); + return llt->llt_delete_addr(llt, flags, l3addr); } static __inline void Modified: projects/routing/sys/netinet/if_ether.c ============================================================================== --- projects/routing/sys/netinet/if_ether.c Sun Dec 7 22:30:54 2014 (r275585) +++ projects/routing/sys/netinet/if_ether.c Sun Dec 7 23:08:07 2014 (r275586) @@ -162,16 +162,19 @@ static const struct netisr_handler arp_n void arp_ifscrub(struct ifnet *ifp, uint32_t addr) { - struct sockaddr_in addr4; + struct sockaddr_in addr4, mask4; bzero((void *)&addr4, sizeof(addr4)); addr4.sin_len = sizeof(addr4); addr4.sin_family = AF_INET; addr4.sin_addr.s_addr = addr; - IF_AFDATA_CFG_WLOCK(ifp); - lltable_delete_lle(LLTABLE(ifp), LLE_IFADDR, - (struct sockaddr *)&addr4); - IF_AFDATA_CFG_WUNLOCK(ifp); + bzero(&mask4, sizeof(mask4)); + mask4.sin_len = sizeof(mask4); + mask4.sin_family = AF_INET; + mask4.sin_addr.s_addr = INADDR_ANY; + + lltable_prefix_free(AF_INET, (struct sockaddr *)&addr4, + (struct sockaddr *)&mask4, LLE_STATIC); } #endif @@ -305,9 +308,14 @@ arp_lltable_clear_entry(struct lltable * } } - /* Finally, free entry */ - pkts_dropped = llentry_free(lle); + lle->la_flags |= LLE_DELETED; + + /* Drop hold queue */ + pkts_dropped = lltable_drop_entry_queue(lle); ARPSTAT_ADD(dropped, pkts_dropped); + + /* Finally, free entry */ + LLE_FREE_LOCKED(lle); } /* @@ -1208,8 +1216,9 @@ arp_update_lle(struct arphdr *ah, struct void arp_ifinit(struct ifnet *ifp, struct ifaddr *ifa) { - struct llentry *lle; + struct llentry *lle, *lle_tmp; struct in_addr addr; + struct lltable *llt; if (ifa->ifa_carp != NULL) return; @@ -1238,6 +1247,7 @@ arp_ifinit(struct ifnet *ifp, struct ifa } IF_AFDATA_CFG_WLOCK(ifp); + llt = LLTABLE(ifp); /* Lock or new shiny lle */ LLE_WLOCK(lle); @@ -1247,18 +1257,26 @@ arp_ifinit(struct ifnet *ifp, struct ifa * Instead of dealing with callouts/flags/etc we simply * delete it and add new one. */ - lltable_delete_lle(LLTABLE(ifp), LLE_IFADDR, + lle_tmp = lltable_lookup_lle(llt, LLE_EXCLUSIVE, (struct sockaddr *)IA_SIN(ifa)); IF_AFDATA_RUN_WLOCK(ifp); + if (lle_tmp != NULL) + lltable_unlink_entry(llt, lle_tmp); bcopy(IF_LLADDR(ifp), &lle->ll_addr, ifp->if_addrlen); lle->la_flags |= (LLE_VALID | LLE_STATIC); lle->r_flags |= RLLE_VALID; - lltable_link_entry(LLTABLE(ifp), lle); + lltable_link_entry(llt, lle); IF_AFDATA_RUN_WUNLOCK(ifp); IF_AFDATA_CFG_WUNLOCK(ifp); + /* XXX: eventhandler */ LLE_WUNLOCK(lle); + + if (lle_tmp != NULL) { + /* XXX: eventhandler */ + llt->llt_clear_entry(llt, lle_tmp); + } } void Modified: projects/routing/sys/netinet/in.c ============================================================================== --- projects/routing/sys/netinet/in.c Sun Dec 7 22:30:54 2014 (r275585) +++ projects/routing/sys/netinet/in.c Sun Dec 7 23:08:07 2014 (r275586) @@ -1137,33 +1137,38 @@ in_lltable_delete(struct lltable *llt, u struct ifnet *ifp = llt->llt_ifp; struct llentry *lle; - IF_AFDATA_CFG_WLOCK_ASSERT(ifp); + IF_AFDATA_CFG_UNLOCK_ASSERT(ifp); KASSERT(l3addr->sa_family == AF_INET, ("sin_family %d", l3addr->sa_family)); + IF_AFDATA_CFG_WLOCK(ifp); lle = in_lltable_find_dst(llt, sin->sin_addr); if (lle == NULL) { + IF_AFDATA_CFG_WUNLOCK(ifp); #ifdef DIAGNOSTIC - log(LOG_INFO, "interface address is missing from cache = %p in delete\n", lle); + log(LOG_INFO, "interface address is missing from cache = %p\n", + lle); #endif return (ENOENT); } - if (!(lle->la_flags & LLE_IFADDR) || (flags & LLE_IFADDR)) { - LLE_WLOCK(lle); - lle->la_flags |= LLE_DELETED; - EVENTHANDLER_INVOKE(lle_event, lle, LLENTRY_DELETED); - IF_AFDATA_RUN_WLOCK(ifp); - lltable_unlink_entry(llt, lle); - IF_AFDATA_RUN_WUNLOCK(ifp); + /* Skipping LLE_IFADDR record */ + if ((lle->la_flags & LLE_IFADDR) != 0 && (flags & LLE_IFADDR) == 0) { + IF_AFDATA_CFG_WUNLOCK(ifp); + return (0); + } + + LLE_WLOCK(lle); + IF_AFDATA_RUN_WLOCK(ifp); + lltable_unlink_entry(llt, lle); + IF_AFDATA_RUN_WUNLOCK(ifp); + IF_AFDATA_CFG_WUNLOCK(ifp); + + EVENTHANDLER_INVOKE(lle_event, lle, LLENTRY_DELETED); #ifdef DIAGNOSTIC log(LOG_INFO, "ifaddr cache = %p is deleted\n", lle); #endif - if ((lle->la_flags & (LLE_STATIC | LLE_IFADDR)) == LLE_STATIC) - llentry_free(lle); - else - LLE_WUNLOCK(lle); - } + llt->llt_clear_entry(llt, lle); return (0); } @@ -1304,7 +1309,7 @@ in_domifattach(struct ifnet *ifp) llt->llt_lookup = in_lltable_lookup; llt->llt_create = in_lltable_create; - llt->llt_delete = in_lltable_delete; + llt->llt_delete_addr = in_lltable_delete; llt->llt_dump_entry = in_lltable_dump_entry; llt->llt_hash = in_lltable_hash; llt->llt_clear_entry = arp_lltable_clear_entry; Modified: projects/routing/sys/netinet6/in6.c ============================================================================== --- projects/routing/sys/netinet6/in6.c Sun Dec 7 22:30:54 2014 (r275585) +++ projects/routing/sys/netinet6/in6.c Sun Dec 7 23:08:07 2014 (r275586) @@ -2173,31 +2173,40 @@ in6_lltable_delete(struct lltable *llt, const struct sockaddr *l3addr) { const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)l3addr; + struct ifnet *ifp; struct llentry *lle; - IF_AFDATA_CFG_WLOCK_ASSERT(llt->llt_ifp); + ifp = llt->llt_ifp; + + IF_AFDATA_CFG_UNLOCK_ASSERT(ifp); KASSERT(l3addr->sa_family == AF_INET6, ("sin_family %d", l3addr->sa_family)); + IF_AFDATA_CFG_WLOCK(ifp); lle = in6_lltable_find_dst(llt, &sin6->sin6_addr); - if (lle == NULL) + if (lle == NULL) { + IF_AFDATA_CFG_WUNLOCK(ifp); return (ENOENT); + } + + /* Skipping LLE_IFADDR record */ + if ((lle->la_flags & LLE_IFADDR) != 0 && (flags & LLE_IFADDR) == 0) { + IF_AFDATA_CFG_WUNLOCK(ifp); + return (0); + } + + LLE_WLOCK(lle); + IF_AFDATA_RUN_WLOCK(ifp); + lltable_unlink_entry(llt, lle); + IF_AFDATA_RUN_WUNLOCK(ifp); + IF_AFDATA_CFG_WUNLOCK(ifp); - if (!(lle->la_flags & LLE_IFADDR) || (flags & LLE_IFADDR)) { - LLE_WLOCK(lle); - lle->la_flags |= LLE_DELETED; - IF_AFDATA_RUN_WLOCK(llt->llt_ifp); - lltable_unlink_entry(llt, lle); - IF_AFDATA_RUN_WUNLOCK(llt->llt_ifp); #ifdef DIAGNOSTIC - log(LOG_INFO, "ifaddr cache = %p is deleted\n", lle); + log(LOG_INFO, "ifaddr cache = %p is deleted\n", lle); #endif - if ((lle->la_flags & (LLE_STATIC | LLE_IFADDR)) == LLE_STATIC) - llentry_free(lle); - else - LLE_WUNLOCK(lle); - } + EVENTHANDLER_INVOKE(lle_event, lle, LLENTRY_DELETED); + llt->llt_clear_entry(llt, lle); return (0); } @@ -2365,7 +2374,7 @@ in6_domifattach(struct ifnet *ifp) llt->llt_lookup = in6_lltable_lookup; llt->llt_create = in6_lltable_create; - llt->llt_delete = in6_lltable_delete; + llt->llt_delete_addr = in6_lltable_delete; llt->llt_dump_entry = in6_lltable_dump_entry; llt->llt_hash = in6_lltable_hash; llt->llt_clear_entry = nd6_lltable_clear_entry; Modified: projects/routing/sys/netinet6/nd6.c ============================================================================== --- projects/routing/sys/netinet6/nd6.c Sun Dec 7 22:30:54 2014 (r275585) +++ projects/routing/sys/netinet6/nd6.c Sun Dec 7 23:08:07 2014 (r275586) @@ -1081,7 +1081,7 @@ nd6_free(struct llentry *ln, int gc) if ((ln->la_flags & LLE_DELETED) != 0) { /* Unlinked entry. Stop timer/callout. */ nd6_llinfo_settimer_locked(ln, -1); - llentry_free(ln); + LLE_FREE_LOCKED(ln); return; } @@ -1132,8 +1132,13 @@ nd6_lltable_clear_entry(struct lltable * /* Check if default router needs to be recalculated */ nd6_check_recalc_defrtr(llt, ln); + /* Drop hold queue */ + lltable_drop_entry_queue(ln); + + ln->la_flags |= LLE_DELETED; + /* Finally, free entry */ - llentry_free(ln); + LLE_FREE_LOCKED(ln); } /* @@ -2460,7 +2465,8 @@ int nd6_add_ifa_lle(struct in6_ifaddr *ia) { struct ifnet *ifp; - struct llentry *ln; + struct llentry *ln, *ln_tmp; + struct lltable *llt; ifp = ia->ia_ifa.ifa_ifp; ia->ia_ifa.ifa_rtrequest = nd6_rtrequest; @@ -2476,20 +2482,36 @@ nd6_add_ifa_lle(struct in6_ifaddr *ia) ln->ln_state = ND6_LLINFO_REACHABLE; IF_AFDATA_CFG_WLOCK(ifp); + llt = LLTABLE6(ifp); /* Lock or new shiny lle */ LLE_WLOCK(ln); - lltable_delete_lle(LLTABLE6(ifp), LLE_IFADDR, + /* + * Check if we already have some corresponding entry. + * Instead of dealing with callouts/flags/etc we simply + * delete it and add new one. + */ + ln_tmp = lltable_lookup_lle(llt, LLE_EXCLUSIVE, (struct sockaddr *)&ia->ia_addr); bcopy(IF_LLADDR(ifp), &ln->ll_addr, ifp->if_addrlen); /* Finally, link our lle to the list */ IF_AFDATA_RUN_WLOCK(ifp); - lltable_link_entry(LLTABLE6(ifp), ln); + if (ln_tmp != NULL) + lltable_unlink_entry(llt, ln_tmp); + lltable_link_entry(llt, ln); IF_AFDATA_RUN_WUNLOCK(ifp); IF_AFDATA_CFG_WUNLOCK(ifp); + /* XXX: event handler? */ LLE_WUNLOCK(ln); + + if (ln_tmp != NULL) { + /* XXX: event handler ? */ + llt->llt_clear_entry(llt, ln_tmp); + } + + in6_newaddrmsg(ia, RTM_ADD); return (0); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201412072308.sB7N87wO084516>