From owner-svn-src-all@FreeBSD.ORG Mon Feb 11 10:58:23 2013 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.FreeBSD.org [8.8.178.115]) by hub.freebsd.org (Postfix) with ESMTP id 75B82CF6; Mon, 11 Feb 2013 10:58:23 +0000 (UTC) (envelope-from glebius@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) by mx1.freebsd.org (Postfix) with ESMTP id 514F81AC4; Mon, 11 Feb 2013 10:58:23 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.5/8.14.5) with ESMTP id r1BAwNOG060850; Mon, 11 Feb 2013 10:58:23 GMT (envelope-from glebius@svn.freebsd.org) Received: (from glebius@localhost) by svn.freebsd.org (8.14.5/8.14.5/Submit) id r1BAwM5r060844; Mon, 11 Feb 2013 10:58:22 GMT (envelope-from glebius@svn.freebsd.org) Message-Id: <201302111058.r1BAwM5r060844@svn.freebsd.org> From: Gleb Smirnoff Date: Mon, 11 Feb 2013 10:58:22 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r246659 - in head/sys: net netinet X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 11 Feb 2013 10:58:23 -0000 Author: glebius Date: Mon Feb 11 10:58:22 2013 New Revision: 246659 URL: http://svnweb.freebsd.org/changeset/base/246659 Log: Resolve source address selection in presense of CARP. Add a couple of helper functions: - carp_master() - boolean function which is true if an address is in the MASTER state. - ifa_preferred() - boolean function that compares two addresses, and is aware of CARP. Utilize ifa_preferred() in ifa_ifwithnet(). The previous version of patch also changed source address selection logic in jails using carp_master(), but we failed to negotiate this part with Bjoern. May be we will approach this problem again later. Reported & tested by: Anton Yuzhaninov Sponsored by: Nginx, Inc Modified: head/sys/net/if.c head/sys/net/if_var.h head/sys/netinet/ip_carp.c head/sys/netinet/ip_carp.h Modified: head/sys/net/if.c ============================================================================== --- head/sys/net/if.c Mon Feb 11 10:14:12 2013 (r246658) +++ head/sys/net/if.c Mon Feb 11 10:58:22 2013 (r246659) @@ -130,6 +130,7 @@ void (*lagg_linkstate_p)(struct ifnet *i /* These are external hooks for CARP. */ void (*carp_linkstate_p)(struct ifnet *ifp); void (*carp_demote_adj_p)(int, char *); +int (*carp_master_p)(struct ifaddr *); #if defined(INET) || defined(INET6) int (*carp_forus_p)(struct ifnet *ifp, u_char *dhost); int (*carp_output_p)(struct ifnet *ifp, struct mbuf *m, @@ -1706,11 +1707,13 @@ next: continue; /* * If the netmask of what we just found * is more specific than what we had before - * (if we had one) then remember the new one - * before continuing to search - * for an even better one. + * (if we had one), or if the virtual status + * of new prefix is better than of the old one, + * then remember the new one before continuing + * to search for an even better one. */ if (ifa_maybe == NULL || + ifa_preferred(ifa_maybe, ifa) || rn_refines((caddr_t)ifa->ifa_netmask, (caddr_t)ifa_maybe->ifa_netmask)) { if (ifa_maybe != NULL) @@ -1782,6 +1785,21 @@ done: return (ifa); } +/* + * See whether new ifa is better than current one: + * 1) A non-virtual one is preferred over virtual. + * 2) A virtual in master state preferred over any other state. + * + * Used in several address selecting functions. + */ +int +ifa_preferred(struct ifaddr *cur, struct ifaddr *next) +{ + + return (cur->ifa_carp && (!next->ifa_carp || + ((*carp_master_p)(next) && !(*carp_master_p)(cur)))); +} + #include /* Modified: head/sys/net/if_var.h ============================================================================== --- head/sys/net/if_var.h Mon Feb 11 10:14:12 2013 (r246658) +++ head/sys/net/if_var.h Mon Feb 11 10:58:22 2013 (r246659) @@ -939,8 +939,8 @@ struct ifaddr *ifa_ifwithdstaddr(struct struct ifaddr *ifa_ifwithnet(struct sockaddr *, int); struct ifaddr *ifa_ifwithroute(int, struct sockaddr *, struct sockaddr *); struct ifaddr *ifa_ifwithroute_fib(int, struct sockaddr *, struct sockaddr *, u_int); - struct ifaddr *ifaof_ifpforaddr(struct sockaddr *, struct ifnet *); +int ifa_preferred(struct ifaddr *, struct ifaddr *); int if_simloop(struct ifnet *ifp, struct mbuf *m, int af, int hlen); Modified: head/sys/netinet/ip_carp.c ============================================================================== --- head/sys/netinet/ip_carp.c Mon Feb 11 10:14:12 2013 (r246658) +++ head/sys/netinet/ip_carp.c Mon Feb 11 10:58:22 2013 (r246659) @@ -969,6 +969,14 @@ carp_ifa_delroute(struct ifaddr *ifa) } } +int +carp_master(struct ifaddr *ifa) +{ + struct carp_softc *sc = ifa->ifa_carp; + + return (sc->sc_state == MASTER); +} + #ifdef INET /* * Broadcast a gratuitous ARP request containing @@ -2072,6 +2080,7 @@ carp_mod_cleanup(void) carp_forus_p = NULL; carp_output_p = NULL; carp_demote_adj_p = NULL; + carp_master_p = NULL; mtx_unlock(&carp_mtx); taskqueue_drain(taskqueue_swi, &carp_sendall_task); mtx_destroy(&carp_mtx); @@ -2092,6 +2101,7 @@ carp_mod_load(void) carp_attach_p = carp_attach; carp_detach_p = carp_detach; carp_demote_adj_p = carp_demote_adj; + carp_master_p = carp_master; #ifdef INET6 carp_iamatch6_p = carp_iamatch6; carp_macmatch6_p = carp_macmatch6; Modified: head/sys/netinet/ip_carp.h ============================================================================== --- head/sys/netinet/ip_carp.h Mon Feb 11 10:14:12 2013 (r246658) +++ head/sys/netinet/ip_carp.h Mon Feb 11 10:58:22 2013 (r246659) @@ -148,6 +148,7 @@ void carp_carpdev_state(struct ifnet *) void carp_input (struct mbuf *, int); int carp6_input (struct mbuf **, int *, int); int carp_output (struct ifnet *, struct mbuf *, struct sockaddr *); +int carp_master(struct ifaddr *); int carp_iamatch(struct ifaddr *, uint8_t **); struct ifaddr *carp_iamatch6(struct ifnet *, struct in6_addr *); caddr_t carp_macmatch6(struct ifnet *, struct mbuf *, const struct in6_addr *); @@ -160,6 +161,7 @@ extern int (*carp_attach_p)(struct ifadd extern void (*carp_detach_p)(struct ifaddr *); extern void (*carp_linkstate_p)(struct ifnet *); extern void (*carp_demote_adj_p)(int, char *); +extern int (*carp_master_p)(struct ifaddr *); /* net/if_bridge.c net/if_ethersubr.c */ extern int (*carp_forus_p)(struct ifnet *, u_char *); /* net/if_ethersubr.c */