|
|
|
/* ip_mp_alg.h: IPV4 multipath algorithm support.
|
|
|
|
*
|
|
|
|
* Copyright (C) 2004, 2005 Einar Lueck <elueck@de.ibm.com>
|
|
|
|
* Copyright (C) 2005 David S. Miller <davem@davemloft.net>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef _NET_IP_MP_ALG_H
|
|
|
|
#define _NET_IP_MP_ALG_H
|
|
|
|
|
|
|
|
#include <linux/ip_mp_alg.h>
|
|
|
|
#include <net/flow.h>
|
|
|
|
#include <net/route.h>
|
|
|
|
|
|
|
|
struct fib_nh;
|
|
|
|
|
|
|
|
struct ip_mp_alg_ops {
|
|
|
|
void (*mp_alg_select_route)(const struct flowi *flp,
|
|
|
|
struct rtable *rth, struct rtable **rp);
|
|
|
|
void (*mp_alg_flush)(void);
|
|
|
|
void (*mp_alg_set_nhinfo)(__be32 network, __be32 netmask,
|
|
|
|
unsigned char prefixlen,
|
|
|
|
const struct fib_nh *nh);
|
|
|
|
void (*mp_alg_remove)(struct rtable *rth);
|
|
|
|
};
|
|
|
|
|
|
|
|
extern int multipath_alg_register(struct ip_mp_alg_ops *, enum ip_mp_alg);
|
|
|
|
extern void multipath_alg_unregister(struct ip_mp_alg_ops *, enum ip_mp_alg);
|
|
|
|
|
|
|
|
extern struct ip_mp_alg_ops *ip_mp_alg_table[];
|
|
|
|
|
|
|
|
static inline int multipath_select_route(const struct flowi *flp,
|
|
|
|
struct rtable *rth,
|
|
|
|
struct rtable **rp)
|
|
|
|
{
|
|
|
|
#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
|
|
|
|
struct ip_mp_alg_ops *ops = ip_mp_alg_table[rth->rt_multipath_alg];
|
|
|
|
|
|
|
|
/* mp_alg_select_route _MUST_ be implemented */
|
|
|
|
if (ops && (rth->u.dst.flags & DST_BALANCED)) {
|
|
|
|
ops->mp_alg_select_route(flp, rth, rp);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void multipath_flush(void)
|
|
|
|
{
|
|
|
|
#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = IP_MP_ALG_NONE; i <= IP_MP_ALG_MAX; i++) {
|
|
|
|
struct ip_mp_alg_ops *ops = ip_mp_alg_table[i];
|
|
|
|
|
|
|
|
if (ops && ops->mp_alg_flush)
|
|
|
|
ops->mp_alg_flush();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void multipath_set_nhinfo(struct rtable *rth,
|
|
|
|
__be32 network, __be32 netmask,
|
|
|
|
unsigned char prefixlen,
|
|
|
|
const struct fib_nh *nh)
|
|
|
|
{
|
|
|
|
#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
|
|
|
|
struct ip_mp_alg_ops *ops = ip_mp_alg_table[rth->rt_multipath_alg];
|
|
|
|
|
|
|
|
if (ops && ops->mp_alg_set_nhinfo)
|
|
|
|
ops->mp_alg_set_nhinfo(network, netmask, prefixlen, nh);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void multipath_remove(struct rtable *rth)
|
|
|
|
{
|
|
|
|
#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
|
|
|
|
struct ip_mp_alg_ops *ops = ip_mp_alg_table[rth->rt_multipath_alg];
|
|
|
|
|
|
|
|
if (ops && ops->mp_alg_remove &&
|
|
|
|
(rth->u.dst.flags & DST_BALANCED))
|
|
|
|
ops->mp_alg_remove(rth);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int multipath_comparekeys(const struct flowi *flp1,
|
|
|
|
const struct flowi *flp2)
|
|
|
|
{
|
|
|
|
return flp1->fl4_dst == flp2->fl4_dst &&
|
|
|
|
flp1->fl4_src == flp2->fl4_src &&
|
|
|
|
flp1->oif == flp2->oif &&
|
|
|
|
flp1->mark == flp2->mark &&
|
|
|
|
!((flp1->fl4_tos ^ flp2->fl4_tos) &
|
|
|
|
(IPTOS_RT_MASK | RTO_ONLINK));
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* _NET_IP_MP_ALG_H */
|