[NETLINK]: fib_lookup() via netlink
Below is a more generic patch to do fib_lookup via netlink. For others we should say that we discussed this as a way to verify route selection. It's also possible there are others uses for this. In short the fist half of struct fib_result_nl is filled in by caller and netlink call fills in the other half and returns it. In case anyone is interested there is a corresponding user app to compare the full routing table this was used to test implementation of the LC-trie. Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
f6e276ee67
commit
246955fe4c
3 changed files with 70 additions and 0 deletions
|
@ -14,6 +14,7 @@
|
|||
#define NETLINK_SELINUX 7 /* SELinux event notifications */
|
||||
#define NETLINK_ARPD 8
|
||||
#define NETLINK_AUDIT 9 /* auditing */
|
||||
#define NETLINK_FIB_LOOKUP 10
|
||||
#define NETLINK_ROUTE6 11 /* af_inet6 route comm channel */
|
||||
#define NETLINK_IP6_FW 13
|
||||
#define NETLINK_DNRTMSG 14 /* DECnet routing messages */
|
||||
|
|
|
@ -109,6 +109,20 @@ struct fib_result {
|
|||
#endif
|
||||
};
|
||||
|
||||
struct fib_result_nl {
|
||||
u32 fl_addr; /* To be looked up*/
|
||||
u32 fl_fwmark;
|
||||
unsigned char fl_tos;
|
||||
unsigned char fl_scope;
|
||||
unsigned char tb_id_in;
|
||||
|
||||
unsigned char tb_id; /* Results */
|
||||
unsigned char prefixlen;
|
||||
unsigned char nh_sel;
|
||||
unsigned char type;
|
||||
unsigned char scope;
|
||||
int err;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_IP_ROUTE_MULTIPATH
|
||||
|
||||
|
|
|
@ -516,6 +516,60 @@ static void fib_del_ifaddr(struct in_ifaddr *ifa)
|
|||
#undef BRD1_OK
|
||||
}
|
||||
|
||||
static void nl_fib_lookup(struct fib_result_nl *frn, struct fib_table *tb )
|
||||
{
|
||||
|
||||
struct fib_result res;
|
||||
struct flowi fl = { .nl_u = { .ip4_u = { .daddr = frn->fl_addr,
|
||||
.fwmark = frn->fl_fwmark,
|
||||
.tos = frn->fl_tos,
|
||||
.scope = frn->fl_scope } } };
|
||||
if (tb) {
|
||||
local_bh_disable();
|
||||
|
||||
frn->tb_id = tb->tb_id;
|
||||
frn->err = tb->tb_lookup(tb, &fl, &res);
|
||||
|
||||
if (!frn->err) {
|
||||
frn->prefixlen = res.prefixlen;
|
||||
frn->nh_sel = res.nh_sel;
|
||||
frn->type = res.type;
|
||||
frn->scope = res.scope;
|
||||
}
|
||||
local_bh_enable();
|
||||
}
|
||||
}
|
||||
|
||||
static void nl_fib_input(struct sock *sk, int len)
|
||||
{
|
||||
struct sk_buff *skb = NULL;
|
||||
struct nlmsghdr *nlh = NULL;
|
||||
struct fib_result_nl *frn;
|
||||
int err;
|
||||
u32 pid;
|
||||
struct fib_table *tb;
|
||||
|
||||
skb = skb_recv_datagram(sk, 0, 0, &err);
|
||||
nlh = (struct nlmsghdr *)skb->data;
|
||||
|
||||
frn = (struct fib_result_nl *) NLMSG_DATA(nlh);
|
||||
tb = fib_get_table(frn->tb_id_in);
|
||||
|
||||
nl_fib_lookup(frn, tb);
|
||||
|
||||
pid = nlh->nlmsg_pid; /*pid of sending process */
|
||||
NETLINK_CB(skb).groups = 0; /* not in mcast group */
|
||||
NETLINK_CB(skb).pid = 0; /* from kernel */
|
||||
NETLINK_CB(skb).dst_pid = pid;
|
||||
NETLINK_CB(skb).dst_groups = 0; /* unicast */
|
||||
netlink_unicast(sk, skb, pid, MSG_DONTWAIT);
|
||||
}
|
||||
|
||||
static void nl_fib_lookup_init(void)
|
||||
{
|
||||
netlink_kernel_create(NETLINK_FIB_LOOKUP, nl_fib_input);
|
||||
}
|
||||
|
||||
static void fib_disable_ip(struct net_device *dev, int force)
|
||||
{
|
||||
if (fib_sync_down(0, dev, force))
|
||||
|
@ -604,6 +658,7 @@ void __init ip_fib_init(void)
|
|||
|
||||
register_netdevice_notifier(&fib_netdev_notifier);
|
||||
register_inetaddr_notifier(&fib_inetaddr_notifier);
|
||||
nl_fib_lookup_init();
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(inet_addr_type);
|
||||
|
|
Loading…
Reference in a new issue