Commit 6a31d2a9 authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller

fib: cleanups

Code style cleanups before upcoming functional changes.
C99 initializer for fib_props array.
Signed-off-by: default avatarEric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e3d32687
...@@ -230,25 +230,28 @@ unsigned int inet_dev_addr_type(struct net *net, const struct net_device *dev, ...@@ -230,25 +230,28 @@ unsigned int inet_dev_addr_type(struct net *net, const struct net_device *dev,
EXPORT_SYMBOL(inet_dev_addr_type); EXPORT_SYMBOL(inet_dev_addr_type);
/* Given (packet source, input interface) and optional (dst, oif, tos): /* Given (packet source, input interface) and optional (dst, oif, tos):
- (main) check, that source is valid i.e. not broadcast or our local * - (main) check, that source is valid i.e. not broadcast or our local
address. * address.
- figure out what "logical" interface this packet arrived * - figure out what "logical" interface this packet arrived
and calculate "specific destination" address. * and calculate "specific destination" address.
- check, that packet arrived from expected physical interface. * - check, that packet arrived from expected physical interface.
*/ */
int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif, int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif,
struct net_device *dev, __be32 *spec_dst, struct net_device *dev, __be32 *spec_dst,
u32 *itag, u32 mark) u32 *itag, u32 mark)
{ {
struct in_device *in_dev; struct in_device *in_dev;
struct flowi fl = { .nl_u = { .ip4_u = struct flowi fl = {
{ .daddr = src, .nl_u = {
.ip4_u = {
.daddr = src,
.saddr = dst, .saddr = dst,
.tos = tos } }, .tos = tos
}
},
.mark = mark, .mark = mark,
.iif = oif }; .iif = oif
};
struct fib_result res; struct fib_result res;
int no_addr, rpf, accept_local; int no_addr, rpf, accept_local;
bool dev_match; bool dev_match;
...@@ -477,9 +480,9 @@ static int rtentry_to_fib_config(struct net *net, int cmd, struct rtentry *rt, ...@@ -477,9 +480,9 @@ static int rtentry_to_fib_config(struct net *net, int cmd, struct rtentry *rt,
} }
/* /*
* Handle IP routing ioctl calls. These are used to manipulate the routing tables * Handle IP routing ioctl calls.
* These are used to manipulate the routing tables
*/ */
int ip_rt_ioctl(struct net *net, unsigned int cmd, void __user *arg) int ip_rt_ioctl(struct net *net, unsigned int cmd, void __user *arg)
{ {
struct fib_config cfg; struct fib_config cfg;
...@@ -523,7 +526,7 @@ int ip_rt_ioctl(struct net *net, unsigned int cmd, void __user *arg) ...@@ -523,7 +526,7 @@ int ip_rt_ioctl(struct net *net, unsigned int cmd, void __user *arg)
return -EINVAL; return -EINVAL;
} }
const struct nla_policy rtm_ipv4_policy[RTA_MAX+1] = { const struct nla_policy rtm_ipv4_policy[RTA_MAX + 1] = {
[RTA_DST] = { .type = NLA_U32 }, [RTA_DST] = { .type = NLA_U32 },
[RTA_SRC] = { .type = NLA_U32 }, [RTA_SRC] = { .type = NLA_U32 },
[RTA_IIF] = { .type = NLA_U32 }, [RTA_IIF] = { .type = NLA_U32 },
...@@ -692,12 +695,11 @@ static int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb) ...@@ -692,12 +695,11 @@ static int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
} }
/* Prepare and feed intra-kernel routing request. /* Prepare and feed intra-kernel routing request.
Really, it should be netlink message, but :-( netlink * Really, it should be netlink message, but :-( netlink
can be not configured, so that we feed it directly * can be not configured, so that we feed it directly
to fib engine. It is legal, because all events occur * to fib engine. It is legal, because all events occur
only when netlink is already locked. * only when netlink is already locked.
*/ */
static void fib_magic(int cmd, int type, __be32 dst, int dst_len, struct in_ifaddr *ifa) static void fib_magic(int cmd, int type, __be32 dst, int dst_len, struct in_ifaddr *ifa)
{ {
struct net *net = dev_net(ifa->ifa_dev->dev); struct net *net = dev_net(ifa->ifa_dev->dev);
...@@ -743,9 +745,9 @@ void fib_add_ifaddr(struct in_ifaddr *ifa) ...@@ -743,9 +745,9 @@ void fib_add_ifaddr(struct in_ifaddr *ifa)
struct in_ifaddr *prim = ifa; struct in_ifaddr *prim = ifa;
__be32 mask = ifa->ifa_mask; __be32 mask = ifa->ifa_mask;
__be32 addr = ifa->ifa_local; __be32 addr = ifa->ifa_local;
__be32 prefix = ifa->ifa_address&mask; __be32 prefix = ifa->ifa_address & mask;
if (ifa->ifa_flags&IFA_F_SECONDARY) { if (ifa->ifa_flags & IFA_F_SECONDARY) {
prim = inet_ifa_byprefix(in_dev, prefix, mask); prim = inet_ifa_byprefix(in_dev, prefix, mask);
if (prim == NULL) { if (prim == NULL) {
printk(KERN_WARNING "fib_add_ifaddr: bug: prim == NULL\n"); printk(KERN_WARNING "fib_add_ifaddr: bug: prim == NULL\n");
...@@ -755,22 +757,24 @@ void fib_add_ifaddr(struct in_ifaddr *ifa) ...@@ -755,22 +757,24 @@ void fib_add_ifaddr(struct in_ifaddr *ifa)
fib_magic(RTM_NEWROUTE, RTN_LOCAL, addr, 32, prim); fib_magic(RTM_NEWROUTE, RTN_LOCAL, addr, 32, prim);
if (!(dev->flags&IFF_UP)) if (!(dev->flags & IFF_UP))
return; return;
/* Add broadcast address, if it is explicitly assigned. */ /* Add broadcast address, if it is explicitly assigned. */
if (ifa->ifa_broadcast && ifa->ifa_broadcast != htonl(0xFFFFFFFF)) if (ifa->ifa_broadcast && ifa->ifa_broadcast != htonl(0xFFFFFFFF))
fib_magic(RTM_NEWROUTE, RTN_BROADCAST, ifa->ifa_broadcast, 32, prim); fib_magic(RTM_NEWROUTE, RTN_BROADCAST, ifa->ifa_broadcast, 32, prim);
if (!ipv4_is_zeronet(prefix) && !(ifa->ifa_flags&IFA_F_SECONDARY) && if (!ipv4_is_zeronet(prefix) && !(ifa->ifa_flags & IFA_F_SECONDARY) &&
(prefix != addr || ifa->ifa_prefixlen < 32)) { (prefix != addr || ifa->ifa_prefixlen < 32)) {
fib_magic(RTM_NEWROUTE, dev->flags&IFF_LOOPBACK ? RTN_LOCAL : fib_magic(RTM_NEWROUTE,
RTN_UNICAST, prefix, ifa->ifa_prefixlen, prim); dev->flags & IFF_LOOPBACK ? RTN_LOCAL : RTN_UNICAST,
prefix, ifa->ifa_prefixlen, prim);
/* Add network specific broadcasts, when it takes a sense */ /* Add network specific broadcasts, when it takes a sense */
if (ifa->ifa_prefixlen < 31) { if (ifa->ifa_prefixlen < 31) {
fib_magic(RTM_NEWROUTE, RTN_BROADCAST, prefix, 32, prim); fib_magic(RTM_NEWROUTE, RTN_BROADCAST, prefix, 32, prim);
fib_magic(RTM_NEWROUTE, RTN_BROADCAST, prefix|~mask, 32, prim); fib_magic(RTM_NEWROUTE, RTN_BROADCAST, prefix | ~mask,
32, prim);
} }
} }
} }
...@@ -781,17 +785,18 @@ static void fib_del_ifaddr(struct in_ifaddr *ifa) ...@@ -781,17 +785,18 @@ static void fib_del_ifaddr(struct in_ifaddr *ifa)
struct net_device *dev = in_dev->dev; struct net_device *dev = in_dev->dev;
struct in_ifaddr *ifa1; struct in_ifaddr *ifa1;
struct in_ifaddr *prim = ifa; struct in_ifaddr *prim = ifa;
__be32 brd = ifa->ifa_address|~ifa->ifa_mask; __be32 brd = ifa->ifa_address | ~ifa->ifa_mask;
__be32 any = ifa->ifa_address&ifa->ifa_mask; __be32 any = ifa->ifa_address & ifa->ifa_mask;
#define LOCAL_OK 1 #define LOCAL_OK 1
#define BRD_OK 2 #define BRD_OK 2
#define BRD0_OK 4 #define BRD0_OK 4
#define BRD1_OK 8 #define BRD1_OK 8
unsigned ok = 0; unsigned ok = 0;
if (!(ifa->ifa_flags&IFA_F_SECONDARY)) if (!(ifa->ifa_flags & IFA_F_SECONDARY))
fib_magic(RTM_DELROUTE, dev->flags&IFF_LOOPBACK ? RTN_LOCAL : fib_magic(RTM_DELROUTE,
RTN_UNICAST, any, ifa->ifa_prefixlen, prim); dev->flags & IFF_LOOPBACK ? RTN_LOCAL : RTN_UNICAST,
any, ifa->ifa_prefixlen, prim);
else { else {
prim = inet_ifa_byprefix(in_dev, any, ifa->ifa_mask); prim = inet_ifa_byprefix(in_dev, any, ifa->ifa_mask);
if (prim == NULL) { if (prim == NULL) {
...@@ -801,9 +806,9 @@ static void fib_del_ifaddr(struct in_ifaddr *ifa) ...@@ -801,9 +806,9 @@ static void fib_del_ifaddr(struct in_ifaddr *ifa)
} }
/* Deletion is more complicated than add. /* Deletion is more complicated than add.
We should take care of not to delete too much :-) * We should take care of not to delete too much :-)
*
Scan address list to be sure that addresses are really gone. * Scan address list to be sure that addresses are really gone.
*/ */
for (ifa1 = in_dev->ifa_list; ifa1; ifa1 = ifa1->ifa_next) { for (ifa1 = in_dev->ifa_list; ifa1; ifa1 = ifa1->ifa_next) {
...@@ -817,22 +822,22 @@ static void fib_del_ifaddr(struct in_ifaddr *ifa) ...@@ -817,22 +822,22 @@ static void fib_del_ifaddr(struct in_ifaddr *ifa)
ok |= BRD0_OK; ok |= BRD0_OK;
} }
if (!(ok&BRD_OK)) if (!(ok & BRD_OK))
fib_magic(RTM_DELROUTE, RTN_BROADCAST, ifa->ifa_broadcast, 32, prim); fib_magic(RTM_DELROUTE, RTN_BROADCAST, ifa->ifa_broadcast, 32, prim);
if (!(ok&BRD1_OK)) if (!(ok & BRD1_OK))
fib_magic(RTM_DELROUTE, RTN_BROADCAST, brd, 32, prim); fib_magic(RTM_DELROUTE, RTN_BROADCAST, brd, 32, prim);
if (!(ok&BRD0_OK)) if (!(ok & BRD0_OK))
fib_magic(RTM_DELROUTE, RTN_BROADCAST, any, 32, prim); fib_magic(RTM_DELROUTE, RTN_BROADCAST, any, 32, prim);
if (!(ok&LOCAL_OK)) { if (!(ok & LOCAL_OK)) {
fib_magic(RTM_DELROUTE, RTN_LOCAL, ifa->ifa_local, 32, prim); fib_magic(RTM_DELROUTE, RTN_LOCAL, ifa->ifa_local, 32, prim);
/* Check, that this local address finally disappeared. */ /* Check, that this local address finally disappeared. */
if (inet_addr_type(dev_net(dev), ifa->ifa_local) != RTN_LOCAL) { if (inet_addr_type(dev_net(dev), ifa->ifa_local) != RTN_LOCAL) {
/* And the last, but not the least thing. /* And the last, but not the least thing.
We must flush stray FIB entries. * We must flush stray FIB entries.
*
First of all, we scan fib_info list searching * First of all, we scan fib_info list searching
for stray nexthop entries, then ignite fib_flush. * for stray nexthop entries, then ignite fib_flush.
*/ */
if (fib_sync_down_addr(dev_net(dev), ifa->ifa_local)) if (fib_sync_down_addr(dev_net(dev), ifa->ifa_local))
fib_flush(dev_net(dev)); fib_flush(dev_net(dev));
...@@ -844,14 +849,20 @@ static void fib_del_ifaddr(struct in_ifaddr *ifa) ...@@ -844,14 +849,20 @@ static void fib_del_ifaddr(struct in_ifaddr *ifa)
#undef BRD1_OK #undef BRD1_OK
} }
static void nl_fib_lookup(struct fib_result_nl *frn, struct fib_table *tb ) static void nl_fib_lookup(struct fib_result_nl *frn, struct fib_table *tb)
{ {
struct fib_result res; struct fib_result res;
struct flowi fl = { .mark = frn->fl_mark, struct flowi fl = {
.nl_u = { .ip4_u = { .daddr = frn->fl_addr, .mark = frn->fl_mark,
.nl_u = {
.ip4_u = {
.daddr = frn->fl_addr,
.tos = frn->fl_tos, .tos = frn->fl_tos,
.scope = frn->fl_scope } } }; .scope = frn->fl_scope
}
}
};
#ifdef CONFIG_IP_MULTIPLE_TABLES #ifdef CONFIG_IP_MULTIPLE_TABLES
res.r = NULL; res.r = NULL;
...@@ -947,7 +958,7 @@ static int fib_inetaddr_event(struct notifier_block *this, unsigned long event, ...@@ -947,7 +958,7 @@ static int fib_inetaddr_event(struct notifier_block *this, unsigned long event,
fib_del_ifaddr(ifa); fib_del_ifaddr(ifa);
if (ifa->ifa_dev->ifa_list == NULL) { if (ifa->ifa_dev->ifa_list == NULL) {
/* Last address was deleted from this interface. /* Last address was deleted from this interface.
Disable IP. * Disable IP.
*/ */
fib_disable_ip(dev, 1, 0); fib_disable_ip(dev, 1, 0);
} else { } else {
......
...@@ -32,8 +32,7 @@ ...@@ -32,8 +32,7 @@
#include <net/ip_fib.h> #include <net/ip_fib.h>
#include <net/fib_rules.h> #include <net/fib_rules.h>
struct fib4_rule struct fib4_rule {
{
struct fib_rule common; struct fib_rule common;
u8 dst_len; u8 dst_len;
u8 src_len; u8 src_len;
...@@ -91,7 +90,8 @@ static int fib4_rule_action(struct fib_rule *rule, struct flowi *flp, ...@@ -91,7 +90,8 @@ static int fib4_rule_action(struct fib_rule *rule, struct flowi *flp,
goto errout; goto errout;
} }
if ((tbl = fib_get_table(rule->fr_net, rule->table)) == NULL) tbl = fib_get_table(rule->fr_net, rule->table);
if (!tbl)
goto errout; goto errout;
err = fib_table_lookup(tbl, flp, (struct fib_result *) arg->result); err = fib_table_lookup(tbl, flp, (struct fib_result *) arg->result);
......
...@@ -60,21 +60,30 @@ static struct hlist_head fib_info_devhash[DEVINDEX_HASHSIZE]; ...@@ -60,21 +60,30 @@ static struct hlist_head fib_info_devhash[DEVINDEX_HASHSIZE];
static DEFINE_SPINLOCK(fib_multipath_lock); static DEFINE_SPINLOCK(fib_multipath_lock);
#define for_nexthops(fi) { int nhsel; const struct fib_nh * nh; \ #define for_nexthops(fi) { \
for (nhsel=0, nh = (fi)->fib_nh; nhsel < (fi)->fib_nhs; nh++, nhsel++) int nhsel; const struct fib_nh *nh; \
for (nhsel = 0, nh = (fi)->fib_nh; \
#define change_nexthops(fi) { int nhsel; struct fib_nh *nexthop_nh; \ nhsel < (fi)->fib_nhs; \
for (nhsel=0, nexthop_nh = (struct fib_nh *)((fi)->fib_nh); nhsel < (fi)->fib_nhs; nexthop_nh++, nhsel++) nh++, nhsel++)
#define change_nexthops(fi) { \
int nhsel; struct fib_nh *nexthop_nh; \
for (nhsel = 0, nexthop_nh = (struct fib_nh *)((fi)->fib_nh); \
nhsel < (fi)->fib_nhs; \
nexthop_nh++, nhsel++)
#else /* CONFIG_IP_ROUTE_MULTIPATH */ #else /* CONFIG_IP_ROUTE_MULTIPATH */
/* Hope, that gcc will optimize it to get rid of dummy loop */ /* Hope, that gcc will optimize it to get rid of dummy loop */
#define for_nexthops(fi) { int nhsel = 0; const struct fib_nh * nh = (fi)->fib_nh; \ #define for_nexthops(fi) { \
for (nhsel=0; nhsel < 1; nhsel++) int nhsel; const struct fib_nh *nh = (fi)->fib_nh; \
for (nhsel = 0; nhsel < 1; nhsel++)
#define change_nexthops(fi) { int nhsel = 0; struct fib_nh *nexthop_nh = (struct fib_nh *)((fi)->fib_nh); \ #define change_nexthops(fi) { \
for (nhsel=0; nhsel < 1; nhsel++) int nhsel; \
struct fib_nh *nexthop_nh = (struct fib_nh *)((fi)->fib_nh); \
for (nhsel = 0; nhsel < 1; nhsel++)
#endif /* CONFIG_IP_ROUTE_MULTIPATH */ #endif /* CONFIG_IP_ROUTE_MULTIPATH */
...@@ -86,54 +95,54 @@ static const struct ...@@ -86,54 +95,54 @@ static const struct
int error; int error;
u8 scope; u8 scope;
} fib_props[RTN_MAX + 1] = { } fib_props[RTN_MAX + 1] = {
{ [RTN_UNSPEC] = {
.error = 0, .error = 0,
.scope = RT_SCOPE_NOWHERE, .scope = RT_SCOPE_NOWHERE,
}, /* RTN_UNSPEC */ },
{ [RTN_UNICAST] = {
.error = 0, .error = 0,
.scope = RT_SCOPE_UNIVERSE, .scope = RT_SCOPE_UNIVERSE,
}, /* RTN_UNICAST */ },
{ [RTN_LOCAL] = {
.error = 0, .error = 0,
.scope = RT_SCOPE_HOST, .scope = RT_SCOPE_HOST,
}, /* RTN_LOCAL */ },
{ [RTN_BROADCAST] = {
.error = 0, .error = 0,
.scope = RT_SCOPE_LINK, .scope = RT_SCOPE_LINK,
}, /* RTN_BROADCAST */ },
{ [RTN_ANYCAST] = {
.error = 0, .error = 0,
.scope = RT_SCOPE_LINK, .scope = RT_SCOPE_LINK,
}, /* RTN_ANYCAST */ },
{ [RTN_MULTICAST] = {
.error = 0, .error = 0,
.scope = RT_SCOPE_UNIVERSE, .scope = RT_SCOPE_UNIVERSE,
}, /* RTN_MULTICAST */ },
{ [RTN_BLACKHOLE] = {
.error = -EINVAL, .error = -EINVAL,
.scope = RT_SCOPE_UNIVERSE, .scope = RT_SCOPE_UNIVERSE,
}, /* RTN_BLACKHOLE */ },
{ [RTN_UNREACHABLE] = {
.error = -EHOSTUNREACH, .error = -EHOSTUNREACH,
.scope = RT_SCOPE_UNIVERSE, .scope = RT_SCOPE_UNIVERSE,
}, /* RTN_UNREACHABLE */ },
{ [RTN_PROHIBIT] = {
.error = -EACCES, .error = -EACCES,
.scope = RT_SCOPE_UNIVERSE, .scope = RT_SCOPE_UNIVERSE,
}, /* RTN_PROHIBIT */ },
{ [RTN_THROW] = {
.error = -EAGAIN, .error = -EAGAIN,
.scope = RT_SCOPE_UNIVERSE, .scope = RT_SCOPE_UNIVERSE,
}, /* RTN_THROW */ },
{ [RTN_NAT] = {
.error = -EINVAL, .error = -EINVAL,
.scope = RT_SCOPE_NOWHERE, .scope = RT_SCOPE_NOWHERE,
}, /* RTN_NAT */ },
{ [RTN_XRESOLVE] = {
.error = -EINVAL, .error = -EINVAL,
.scope = RT_SCOPE_NOWHERE, .scope = RT_SCOPE_NOWHERE,
}, /* RTN_XRESOLVE */ },
}; };
...@@ -142,7 +151,7 @@ static const struct ...@@ -142,7 +151,7 @@ static const struct
void free_fib_info(struct fib_info *fi) void free_fib_info(struct fib_info *fi)
{ {
if (fi->fib_dead == 0) { if (fi->fib_dead == 0) {
printk(KERN_WARNING "Freeing alive fib_info %p\n", fi); pr_warning("Freeing alive fib_info %p\n", fi);
return; return;
} }
change_nexthops(fi) { change_nexthops(fi) {
...@@ -173,7 +182,7 @@ void fib_release_info(struct fib_info *fi) ...@@ -173,7 +182,7 @@ void fib_release_info(struct fib_info *fi)
spin_unlock_bh(&fib_info_lock); spin_unlock_bh(&fib_info_lock);
} }
static __inline__ int nh_comp(const struct fib_info *fi, const struct fib_info *ofi) static inline int nh_comp(const struct fib_info *fi, const struct fib_info *ofi)
{ {
const struct fib_nh *onh = ofi->fib_nh; const struct fib_nh *onh = ofi->fib_nh;
...@@ -187,7 +196,7 @@ static __inline__ int nh_comp(const struct fib_info *fi, const struct fib_info * ...@@ -187,7 +196,7 @@ static __inline__ int nh_comp(const struct fib_info *fi, const struct fib_info *
#ifdef CONFIG_NET_CLS_ROUTE #ifdef CONFIG_NET_CLS_ROUTE
nh->nh_tclassid != onh->nh_tclassid || nh->nh_tclassid != onh->nh_tclassid ||
#endif #endif
((nh->nh_flags^onh->nh_flags)&~RTNH_F_DEAD)) ((nh->nh_flags ^ onh->nh_flags) & ~RTNH_F_DEAD))
return -1; return -1;
onh++; onh++;
} endfor_nexthops(fi); } endfor_nexthops(fi);
...@@ -238,7 +247,7 @@ static struct fib_info *fib_find_info(const struct fib_info *nfi) ...@@ -238,7 +247,7 @@ static struct fib_info *fib_find_info(const struct fib_info *nfi)
nfi->fib_priority == fi->fib_priority && nfi->fib_priority == fi->fib_priority &&
memcmp(nfi->fib_metrics, fi->fib_metrics, memcmp(nfi->fib_metrics, fi->fib_metrics,
sizeof(fi->fib_metrics)) == 0 && sizeof(fi->fib_metrics)) == 0 &&
((nfi->fib_flags^fi->fib_flags)&~RTNH_F_DEAD) == 0 && ((nfi->fib_flags ^ fi->fib_flags) & ~RTNH_F_DEAD) == 0 &&
(nfi->fib_nhs == 0 || nh_comp(fi, nfi) == 0)) (nfi->fib_nhs == 0 || nh_comp(fi, nfi) == 0))
return fi; return fi;
} }
...@@ -247,9 +256,8 @@ static struct fib_info *fib_find_info(const struct fib_info *nfi) ...@@ -247,9 +256,8 @@ static struct fib_info *fib_find_info(const struct fib_info *nfi)
} }
/* Check, that the gateway is already configured. /* Check, that the gateway is already configured.
Used only by redirect accept routine. * Used only by redirect accept routine.
*/ */
int ip_fib_check_default(__be32 gw, struct net_device *dev) int ip_fib_check_default(__be32 gw, struct net_device *dev)
{ {
struct hlist_head *head; struct hlist_head *head;
...@@ -264,7 +272,7 @@ int ip_fib_check_default(__be32 gw, struct net_device *dev) ...@@ -264,7 +272,7 @@ int ip_fib_check_default(__be32 gw, struct net_device *dev)
hlist_for_each_entry(nh, node, head, nh_hash) { hlist_for_each_entry(nh, node, head, nh_hash) {
if (nh->nh_dev == dev && if (nh->nh_dev == dev &&
nh->nh_gw == gw && nh->nh_gw == gw &&
!(nh->nh_flags&RTNH_F_DEAD)) { !(nh->nh_flags & RTNH_F_DEAD)) {
spin_unlock(&fib_info_lock); spin_unlock(&fib_info_lock);
return 0; return 0;
} }
...@@ -362,10 +370,10 @@ int fib_detect_death(struct fib_info *fi, int order, ...@@ -362,10 +370,10 @@ int fib_detect_death(struct fib_info *fi, int order,
} }
if (state == NUD_REACHABLE) if (state == NUD_REACHABLE)
return 0; return 0;
if ((state&NUD_VALID) && order != dflt) if ((state & NUD_VALID) && order != dflt)
return 0; return 0;
if ((state&NUD_VALID) || if ((state & NUD_VALID) ||
(*last_idx<0 && order > dflt)) { (*last_idx < 0 && order > dflt)) {
*last_resort = fi; *last_resort = fi;
*last_idx = order; *last_idx = order;
} }
...@@ -476,69 +484,69 @@ int fib_nh_match(struct fib_config *cfg, struct fib_info *fi) ...@@ -476,69 +484,69 @@ int fib_nh_match(struct fib_config *cfg, struct fib_info *fi)
/* /*
Picture * Picture
------- * -------
*
Semantics of nexthop is very messy by historical reasons. * Semantics of nexthop is very messy by historical reasons.
We have to take into account, that: * We have to take into account, that:
a) gateway can be actually local interface address, * a) gateway can be actually local interface address,
so that gatewayed route is direct. * so that gatewayed route is direct.
b) gateway must be on-link address, possibly * b) gateway must be on-link address, possibly
described not by an ifaddr, but also by a direct route. * described not by an ifaddr, but also by a direct route.
c) If both gateway and interface are specified, they should not * c) If both gateway and interface are specified, they should not
contradict. * contradict.
d) If we use tunnel routes, gateway could be not on-link. * d) If we use tunnel routes, gateway could be not on-link.
*
Attempt to reconcile all of these (alas, self-contradictory) conditions * Attempt to reconcile all of these (alas, self-contradictory) conditions
results in pretty ugly and hairy code with obscure logic. * results in pretty ugly and hairy code with obscure logic.
*
I chose to generalized it instead, so that the size * I chose to generalized it instead, so that the size
of code does not increase practically, but it becomes * of code does not increase practically, but it becomes
much more general. * much more general.
Every prefix is assigned a "scope" value: "host" is local address, * Every prefix is assigned a "scope" value: "host" is local address,
"link" is direct route, * "link" is direct route,
[ ... "site" ... "interior" ... ] * [ ... "site" ... "interior" ... ]
and "universe" is true gateway route with global meaning. * and "universe" is true gateway route with global meaning.
*
Every prefix refers to a set of "nexthop"s (gw, oif), * Every prefix refers to a set of "nexthop"s (gw, oif),
where gw must have narrower scope. This recursion stops * where gw must have narrower scope. This recursion stops
when gw has LOCAL scope or if "nexthop" is declared ONLINK, * when gw has LOCAL scope or if "nexthop" is declared ONLINK,
which means that gw is forced to be on link. * which means that gw is forced to be on link.
*
Code is still hairy, but now it is apparently logically * Code is still hairy, but now it is apparently logically
consistent and very flexible. F.e. as by-product it allows * consistent and very flexible. F.e. as by-product it allows
to co-exists in peace independent exterior and interior * to co-exists in peace independent exterior and interior
routing processes. * routing processes.
*
Normally it looks as following. * Normally it looks as following.
*
{universe prefix} -> (gw, oif) [scope link] * {universe prefix} -> (gw, oif) [scope link]
| * |
|-> {link prefix} -> (gw, oif) [scope local] * |-> {link prefix} -> (gw, oif) [scope local]
| * |
|-> {local prefix} (terminal node) * |-> {local prefix} (terminal node)
*/ */
static int fib_check_nh(struct fib_config *cfg, struct fib_info *fi, static int fib_check_nh(struct fib_config *cfg, struct fib_info *fi,
struct fib_nh *nh) struct fib_nh *nh)
{ {
int err; int err;
struct net *net; struct net *net;
struct net_device *dev;
net = cfg->fc_nlinfo.nl_net; net = cfg->fc_nlinfo.nl_net;
if (nh->nh_gw) { if (nh->nh_gw) {
struct fib_result res; struct fib_result res;
if (nh->nh_flags&RTNH_F_ONLINK) { if (nh->nh_flags & RTNH_F_ONLINK) {
struct net_device *dev;
if (cfg->fc_scope >= RT_SCOPE_LINK) if (cfg->fc_scope >= RT_SCOPE_LINK)
return -EINVAL; return -EINVAL;
if (inet_addr_type(net, nh->nh_gw) != RTN_UNICAST) if (inet_addr_type(net, nh->nh_gw) != RTN_UNICAST)
return -EINVAL; return -EINVAL;
if ((dev = __dev_get_by_index(net, nh->nh_oif)) == NULL) dev = __dev_get_by_index(net, nh->nh_oif);
if (!dev)
return -ENODEV; return -ENODEV;
if (!(dev->flags&IFF_UP)) if (!(dev->flags & IFF_UP))
return -ENETDOWN; return -ENETDOWN;
nh->nh_dev = dev; nh->nh_dev = dev;
dev_hold(dev); dev_hold(dev);
...@@ -559,7 +567,8 @@ static int fib_check_nh(struct fib_config *cfg, struct fib_info *fi, ...@@ -559,7 +567,8 @@ static int fib_check_nh(struct fib_config *cfg, struct fib_info *fi,
/* It is not necessary, but requires a bit of thinking */ /* It is not necessary, but requires a bit of thinking */
if (fl.fl4_scope < RT_SCOPE_LINK) if (fl.fl4_scope < RT_SCOPE_LINK)
fl.fl4_scope = RT_SCOPE_LINK; fl.fl4_scope = RT_SCOPE_LINK;
if ((err = fib_lookup(net, &fl, &res)) != 0) err = fib_lookup(net, &fl, &res);
if (err)
return err; return err;
} }
err = -EINVAL; err = -EINVAL;
...@@ -567,11 +576,12 @@ static int fib_check_nh(struct fib_config *cfg, struct fib_info *fi, ...@@ -567,11 +576,12 @@ static int fib_check_nh(struct fib_config *cfg, struct fib_info *fi,
goto out; goto out;
nh->nh_scope = res.scope; nh->nh_scope = res.scope;
nh->nh_oif = FIB_RES_OIF(res); nh->nh_oif = FIB_RES_OIF(res);
if ((nh->nh_dev = FIB_RES_DEV(res)) == NULL) nh->nh_dev = dev = FIB_RES_DEV(res);
if (!dev)
goto out; goto out;
dev_hold(nh->nh_dev); dev_hold(dev);
err = -ENETDOWN; err = -ENETDOWN;
if (!(nh->nh_dev->flags & IFF_UP)) if (!(dev->flags & IFF_UP))
goto out; goto out;
err = 0; err = 0;
out: out:
...@@ -580,13 +590,13 @@ static int fib_check_nh(struct fib_config *cfg, struct fib_info *fi, ...@@ -580,13 +590,13 @@ static int fib_check_nh(struct fib_config *cfg, struct fib_info *fi,
} else { } else {
struct in_device *in_dev; struct in_device *in_dev;
if (nh->nh_flags&(RTNH_F_PERVASIVE|RTNH_F_ONLINK)) if (nh->nh_flags & (RTNH_F_PERVASIVE | RTNH_F_ONLINK))
return -EINVAL; return -EINVAL;
in_dev = inetdev_by_index(net, nh->nh_oif); in_dev = inetdev_by_index(net, nh->nh_oif);
if (in_dev == NULL) if (in_dev == NULL)
return -ENODEV; return -ENODEV;
if (!(in_dev->dev->flags&IFF_UP)) { if (!(in_dev->dev->flags & IFF_UP)) {
in_dev_put(in_dev); in_dev_put(in_dev);
return -ENETDOWN; return -ENETDOWN;
} }
...@@ -602,7 +612,9 @@ static inline unsigned int fib_laddr_hashfn(__be32 val) ...@@ -602,7 +612,9 @@ static inline unsigned int fib_laddr_hashfn(__be32 val)
{ {
unsigned int mask = (fib_hash_size - 1); unsigned int mask = (fib_hash_size - 1);
return ((__force u32)val ^ ((__force u32)val >> 7) ^ ((__force u32)val >> 14)) & mask; return ((__force u32)val ^
((__force u32)val >> 7) ^
((__force u32)val >> 14)) & mask;
} }
static struct hlist_head *fib_hash_alloc(int bytes) static struct hlist_head *fib_hash_alloc(int bytes)
...@@ -611,7 +623,8 @@ static struct hlist_head *fib_hash_alloc(int bytes) ...@@ -611,7 +623,8 @@ static struct hlist_head *fib_hash_alloc(int bytes)
return kzalloc(bytes, GFP_KERNEL); return kzalloc(bytes, GFP_KERNEL);
else else
return (struct hlist_head *) return (struct hlist_head *)
__get_free_pages(GFP_KERNEL | __GFP_ZERO, get_order(bytes)); __get_free_pages(GFP_KERNEL | __GFP_ZERO,
get_order(bytes));
} }
static void fib_hash_free(struct hlist_head *hash, int bytes) static void fib_hash_free(struct hlist_head *hash, int bytes)
...@@ -806,7 +819,8 @@ struct fib_info *fib_create_info(struct fib_config *cfg) ...@@ -806,7 +819,8 @@ struct fib_info *fib_create_info(struct fib_config *cfg)
goto failure; goto failure;
} else { } else {
change_nexthops(fi) { change_nexthops(fi) {
if ((err = fib_check_nh(cfg, fi, nexthop_nh)) != 0) err = fib_check_nh(cfg, fi, nexthop_nh);
if (err != 0)
goto failure; goto failure;
} endfor_nexthops(fi) } endfor_nexthops(fi)
} }
...@@ -819,7 +833,8 @@ struct fib_info *fib_create_info(struct fib_config *cfg) ...@@ -819,7 +833,8 @@ struct fib_info *fib_create_info(struct fib_config *cfg)
} }
link_it: link_it:
if ((ofi = fib_find_info(fi)) != NULL) { ofi = fib_find_info(fi);
if (ofi) {
fi->fib_dead = 1; fi->fib_dead = 1;
free_fib_info(fi); free_fib_info(fi);
ofi->fib_treeref++; ofi->fib_treeref++;
...@@ -895,7 +910,7 @@ int fib_semantic_match(struct list_head *head, const struct flowi *flp, ...@@ -895,7 +910,7 @@ int fib_semantic_match(struct list_head *head, const struct flowi *flp,
case RTN_ANYCAST: case RTN_ANYCAST:
case RTN_MULTICAST: case RTN_MULTICAST:
for_nexthops(fi) { for_nexthops(fi) {
if (nh->nh_flags&RTNH_F_DEAD) if (nh->nh_flags & RTNH_F_DEAD)
continue; continue;
if (!flp->oif || flp->oif == nh->nh_oif) if (!flp->oif || flp->oif == nh->nh_oif)
break; break;
...@@ -906,15 +921,14 @@ int fib_semantic_match(struct list_head *head, const struct flowi *flp, ...@@ -906,15 +921,14 @@ int fib_semantic_match(struct list_head *head, const struct flowi *flp,
goto out_fill_res; goto out_fill_res;
} }
#else #else
if (nhsel < 1) { if (nhsel < 1)
goto out_fill_res; goto out_fill_res;
}
#endif #endif
endfor_nexthops(fi); endfor_nexthops(fi);
continue; continue;
default: default:
printk(KERN_WARNING "fib_semantic_match bad type %#x\n", pr_warning("fib_semantic_match bad type %#x\n",
fa->fa_type); fa->fa_type);
return -EINVAL; return -EINVAL;
} }
...@@ -1028,10 +1042,10 @@ int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event, ...@@ -1028,10 +1042,10 @@ int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
} }
/* /*
Update FIB if: * Update FIB if:
- local address disappeared -> we must delete all the entries * - local address disappeared -> we must delete all the entries
referring to it. * referring to it.
- device went down -> we must shutdown all nexthops going via it. * - device went down -> we must shutdown all nexthops going via it.
*/ */
int fib_sync_down_addr(struct net *net, __be32 local) int fib_sync_down_addr(struct net *net, __be32 local)
{ {
...@@ -1078,7 +1092,7 @@ int fib_sync_down_dev(struct net_device *dev, int force) ...@@ -1078,7 +1092,7 @@ int fib_sync_down_dev(struct net_device *dev, int force)
prev_fi = fi; prev_fi = fi;
dead = 0; dead = 0;
change_nexthops(fi) { change_nexthops(fi) {
if (nexthop_nh->nh_flags&RTNH_F_DEAD) if (nexthop_nh->nh_flags & RTNH_F_DEAD)
dead++; dead++;
else if (nexthop_nh->nh_dev == dev && else if (nexthop_nh->nh_dev == dev &&
nexthop_nh->nh_scope != scope) { nexthop_nh->nh_scope != scope) {
...@@ -1110,10 +1124,9 @@ int fib_sync_down_dev(struct net_device *dev, int force) ...@@ -1110,10 +1124,9 @@ int fib_sync_down_dev(struct net_device *dev, int force)
#ifdef CONFIG_IP_ROUTE_MULTIPATH #ifdef CONFIG_IP_ROUTE_MULTIPATH
/* /*
Dead device goes up. We wake up dead nexthops. * Dead device goes up. We wake up dead nexthops.
It takes sense only on multipath routes. * It takes sense only on multipath routes.
*/ */
int fib_sync_up(struct net_device *dev) int fib_sync_up(struct net_device *dev)
{ {
struct fib_info *prev_fi; struct fib_info *prev_fi;
...@@ -1123,7 +1136,7 @@ int fib_sync_up(struct net_device *dev) ...@@ -1123,7 +1136,7 @@ int fib_sync_up(struct net_device *dev)
struct fib_nh *nh; struct fib_nh *nh;
int ret; int ret;
if (!(dev->flags&IFF_UP)) if (!(dev->flags & IFF_UP))
return 0; return 0;
prev_fi = NULL; prev_fi = NULL;
...@@ -1142,12 +1155,12 @@ int fib_sync_up(struct net_device *dev) ...@@ -1142,12 +1155,12 @@ int fib_sync_up(struct net_device *dev)
prev_fi = fi; prev_fi = fi;
alive = 0; alive = 0;
change_nexthops(fi) { change_nexthops(fi) {
if (!(nexthop_nh->nh_flags&RTNH_F_DEAD)) { if (!(nexthop_nh->nh_flags & RTNH_F_DEAD)) {
alive++; alive++;
continue; continue;
} }
if (nexthop_nh->nh_dev == NULL || if (nexthop_nh->nh_dev == NULL ||
!(nexthop_nh->nh_dev->flags&IFF_UP)) !(nexthop_nh->nh_dev->flags & IFF_UP))
continue; continue;
if (nexthop_nh->nh_dev != dev || if (nexthop_nh->nh_dev != dev ||
!__in_dev_get_rtnl(dev)) !__in_dev_get_rtnl(dev))
...@@ -1169,10 +1182,9 @@ int fib_sync_up(struct net_device *dev) ...@@ -1169,10 +1182,9 @@ int fib_sync_up(struct net_device *dev)
} }
/* /*
The algorithm is suboptimal, but it provides really * The algorithm is suboptimal, but it provides really
fair weighted route distribution. * fair weighted route distribution.
*/ */
void fib_select_multipath(const struct flowi *flp, struct fib_result *res) void fib_select_multipath(const struct flowi *flp, struct fib_result *res)
{ {
struct fib_info *fi = res->fi; struct fib_info *fi = res->fi;
...@@ -1182,7 +1194,7 @@ void fib_select_multipath(const struct flowi *flp, struct fib_result *res) ...@@ -1182,7 +1194,7 @@ void fib_select_multipath(const struct flowi *flp, struct fib_result *res)
if (fi->fib_power <= 0) { if (fi->fib_power <= 0) {
int power = 0; int power = 0;
change_nexthops(fi) { change_nexthops(fi) {
if (!(nexthop_nh->nh_flags&RTNH_F_DEAD)) { if (!(nexthop_nh->nh_flags & RTNH_F_DEAD)) {
power += nexthop_nh->nh_weight; power += nexthop_nh->nh_weight;
nexthop_nh->nh_power = nexthop_nh->nh_weight; nexthop_nh->nh_power = nexthop_nh->nh_weight;
} }
...@@ -1198,15 +1210,16 @@ void fib_select_multipath(const struct flowi *flp, struct fib_result *res) ...@@ -1198,15 +1210,16 @@ void fib_select_multipath(const struct flowi *flp, struct fib_result *res)
/* w should be random number [0..fi->fib_power-1], /* w should be random number [0..fi->fib_power-1],
it is pretty bad approximation. * it is pretty bad approximation.
*/ */
w = jiffies % fi->fib_power; w = jiffies % fi->fib_power;
change_nexthops(fi) { change_nexthops(fi) {
if (!(nexthop_nh->nh_flags&RTNH_F_DEAD) && if (!(nexthop_nh->nh_flags & RTNH_F_DEAD) &&
nexthop_nh->nh_power) { nexthop_nh->nh_power) {
if ((w -= nexthop_nh->nh_power) <= 0) { w -= nexthop_nh->nh_power;
if (w <= 0) {
nexthop_nh->nh_power--; nexthop_nh->nh_power--;
fi->fib_power--; fi->fib_power--;
res->nh_sel = nhsel; res->nh_sel = nhsel;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment