/* 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 */
/* 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 */