Linux-2.6.12-rc2
[cascardo/linux.git] / include / net / ip_mp_alg.h
1 /* ip_mp_alg.h: IPV4 multipath algorithm support.
2  *
3  * Copyright (C) 2004, 2005 Einar Lueck <elueck@de.ibm.com>
4  * Copyright (C) 2005 David S. Miller <davem@davemloft.net>
5  */
6
7 #ifndef _NET_IP_MP_ALG_H
8 #define _NET_IP_MP_ALG_H
9
10 #include <linux/config.h>
11 #include <linux/ip_mp_alg.h>
12 #include <net/flow.h>
13 #include <net/route.h>
14
15 struct fib_nh;
16
17 struct ip_mp_alg_ops {
18         void    (*mp_alg_select_route)(const struct flowi *flp,
19                                        struct rtable *rth, struct rtable **rp);
20         void    (*mp_alg_flush)(void);
21         void    (*mp_alg_set_nhinfo)(__u32 network, __u32 netmask,
22                                      unsigned char prefixlen,
23                                      const struct fib_nh *nh);
24         void    (*mp_alg_remove)(struct rtable *rth);
25 };
26
27 extern int multipath_alg_register(struct ip_mp_alg_ops *, enum ip_mp_alg);
28 extern void multipath_alg_unregister(struct ip_mp_alg_ops *, enum ip_mp_alg);
29
30 extern struct ip_mp_alg_ops *ip_mp_alg_table[];
31
32 static inline int multipath_select_route(const struct flowi *flp,
33                                          struct rtable *rth,
34                                          struct rtable **rp)
35 {
36 #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
37         struct ip_mp_alg_ops *ops = ip_mp_alg_table[rth->rt_multipath_alg];
38
39         /* mp_alg_select_route _MUST_ be implemented */
40         if (ops && (rth->u.dst.flags & DST_BALANCED)) {
41                 ops->mp_alg_select_route(flp, rth, rp);
42                 return 1;
43         }
44 #endif
45         return 0;
46 }
47
48 static inline void multipath_flush(void)
49 {
50 #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
51         int i;
52
53         for (i = IP_MP_ALG_NONE; i <= IP_MP_ALG_MAX; i++) {
54                 struct ip_mp_alg_ops *ops = ip_mp_alg_table[i];
55
56                 if (ops && ops->mp_alg_flush)
57                         ops->mp_alg_flush();
58         }
59 #endif
60 }
61
62 static inline void multipath_set_nhinfo(struct rtable *rth,
63                                         __u32 network, __u32 netmask,
64                                         unsigned char prefixlen,
65                                         const struct fib_nh *nh)
66 {
67 #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
68         struct ip_mp_alg_ops *ops = ip_mp_alg_table[rth->rt_multipath_alg];
69
70         if (ops && ops->mp_alg_set_nhinfo)
71                 ops->mp_alg_set_nhinfo(network, netmask, prefixlen, nh);
72 #endif
73 }
74
75 static inline void multipath_remove(struct rtable *rth)
76 {
77 #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
78         struct ip_mp_alg_ops *ops = ip_mp_alg_table[rth->rt_multipath_alg];
79
80         if (ops && ops->mp_alg_remove &&
81             (rth->u.dst.flags & DST_BALANCED))
82                 ops->mp_alg_remove(rth);
83 #endif
84 }
85
86 static inline int multipath_comparekeys(const struct flowi *flp1,
87                                         const struct flowi *flp2)
88 {
89         return flp1->fl4_dst == flp2->fl4_dst &&
90                 flp1->fl4_src == flp2->fl4_src &&
91                 flp1->oif == flp2->oif &&
92 #ifdef CONFIG_IP_ROUTE_FWMARK
93                 flp1->fl4_fwmark == flp2->fl4_fwmark &&
94 #endif
95                 !((flp1->fl4_tos ^ flp2->fl4_tos) &
96                   (IPTOS_RT_MASK | RTO_ONLINK));
97 }
98
99 #endif /* _NET_IP_MP_ALG_H */