svn commit: r246659 - in head/sys: net netinet
Gleb Smirnoff
glebius at FreeBSD.org
Mon Feb 11 10:58:23 UTC 2013
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 <citrin citrin.ru>
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 <net/if_llatbl.h>
/*
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 */
More information about the svn-src-all
mailing list