Merge to Fedora kernel-2.6.18-1.2224_FC5 patched with stable patch-2.6.18.1-vs2.0...
[linux-2.6.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/ip_mp_alg.h>
11 #include <net/flow.h>
12 #include <net/route.h>
13
14 struct fib_nh;
15
16 struct ip_mp_alg_ops {
17         void    (*mp_alg_select_route)(const struct flowi *flp,
18                                        struct rtable *rth, struct rtable **rp);
19         void    (*mp_alg_flush)(void);
20         void    (*mp_alg_set_nhinfo)(__u32 network, __u32 netmask,
21                                      unsigned char prefixlen,
22                                      const struct fib_nh *nh);
23         void    (*mp_alg_remove)(struct rtable *rth);
24 };
25
26 extern int multipath_alg_register(struct ip_mp_alg_ops *, enum ip_mp_alg);
27 extern void multipath_alg_unregister(struct ip_mp_alg_ops *, enum ip_mp_alg);
28
29 extern struct ip_mp_alg_ops *ip_mp_alg_table[];
30
31 static inline int multipath_select_route(const struct flowi *flp,
32                                          struct rtable *rth,
33                                          struct rtable **rp)
34 {
35 #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
36         struct ip_mp_alg_ops *ops = ip_mp_alg_table[rth->rt_multipath_alg];
37
38         /* mp_alg_select_route _MUST_ be implemented */
39         if (ops && (rth->u.dst.flags & DST_BALANCED)) {
40                 ops->mp_alg_select_route(flp, rth, rp);
41                 return 1;
42         }
43 #endif
44         return 0;
45 }
46
47 static inline void multipath_flush(void)
48 {
49 #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
50         int i;
51
52         for (i = IP_MP_ALG_NONE; i <= IP_MP_ALG_MAX; i++) {
53                 struct ip_mp_alg_ops *ops = ip_mp_alg_table[i];
54
55                 if (ops && ops->mp_alg_flush)
56                         ops->mp_alg_flush();
57         }
58 #endif
59 }
60
61 static inline void multipath_set_nhinfo(struct rtable *rth,
62                                         __u32 network, __u32 netmask,
63                                         unsigned char prefixlen,
64                                         const struct fib_nh *nh)
65 {
66 #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
67         struct ip_mp_alg_ops *ops = ip_mp_alg_table[rth->rt_multipath_alg];
68
69         if (ops && ops->mp_alg_set_nhinfo)
70                 ops->mp_alg_set_nhinfo(network, netmask, prefixlen, nh);
71 #endif
72 }
73
74 static inline void multipath_remove(struct rtable *rth)
75 {
76 #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
77         struct ip_mp_alg_ops *ops = ip_mp_alg_table[rth->rt_multipath_alg];
78
79         if (ops && ops->mp_alg_remove &&
80             (rth->u.dst.flags & DST_BALANCED))
81                 ops->mp_alg_remove(rth);
82 #endif
83 }
84
85 static inline int multipath_comparekeys(const struct flowi *flp1,
86                                         const struct flowi *flp2)
87 {
88         return flp1->fl4_dst == flp2->fl4_dst &&
89                 flp1->fl4_src == flp2->fl4_src &&
90                 flp1->oif == flp2->oif &&
91 #ifdef CONFIG_IP_ROUTE_FWMARK
92                 flp1->fl4_fwmark == flp2->fl4_fwmark &&
93 #endif
94                 !((flp1->fl4_tos ^ flp2->fl4_tos) &
95                   (IPTOS_RT_MASK | RTO_ONLINK));
96 }
97
98 #endif /* _NET_IP_MP_ALG_H */