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
This commit is contained in:
parent
98744c5a84
commit
24421c1c32
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=246659
24
sys/net/if.c
24
sys/net/if.c
@ -130,6 +130,7 @@ void (*lagg_linkstate_p)(struct ifnet *ifp, int state);
|
||||
/* 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 @@ ifaof_ifpforaddr(struct sockaddr *addr, struct ifnet *ifp)
|
||||
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>
|
||||
|
||||
/*
|
||||
|
@ -939,8 +939,8 @@ struct ifaddr *ifa_ifwithdstaddr(struct sockaddr *);
|
||||
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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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 ifaddr *, int);
|
||||
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 */
|
||||
|
Loading…
Reference in New Issue
Block a user