⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dn_fib.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 2 页
字号:
	int err = dn_fib_props[type].error;	if (err == 0) {		if (fi->fib_flags & RTNH_F_DEAD)			return 1;		res->fi = fi;		switch(type) {			case RTN_NAT:				DN_FIB_RES_RESET(*res);				atomic_inc(&fi->fib_clntref);				return 0;			case RTN_UNICAST:			case RTN_LOCAL:				for_nexthops(fi) {					if (nh->nh_flags & RTNH_F_DEAD)						continue;					if (!fl->oif || fl->oif == nh->nh_oif)						break;				}				if (nhsel < fi->fib_nhs) {					res->nh_sel = nhsel;					atomic_inc(&fi->fib_clntref);					return 0;				}				endfor_nexthops(fi);				res->fi = NULL;				return 1;			default:				if (net_ratelimit())					 printk("DECnet: impossible routing event : dn_fib_semantic_match type=%d\n", type);				res->fi = NULL;				return -EINVAL;		}	}	return err;}void dn_fib_select_multipath(const struct flowi *fl, struct dn_fib_res *res){	struct dn_fib_info *fi = res->fi;	int w;	spin_lock_bh(&dn_fib_multipath_lock);	if (fi->fib_power <= 0) {		int power = 0;		change_nexthops(fi) {			if (!(nh->nh_flags&RTNH_F_DEAD)) {				power += nh->nh_weight;				nh->nh_power = nh->nh_weight;			}		} endfor_nexthops(fi);		fi->fib_power = power;		if (power < 0) {			spin_unlock_bh(&dn_fib_multipath_lock);			res->nh_sel = 0;			return;		}	}	w = jiffies % fi->fib_power;	change_nexthops(fi) {		if (!(nh->nh_flags&RTNH_F_DEAD) && nh->nh_power) {			if ((w -= nh->nh_power) <= 0) {				nh->nh_power--;				fi->fib_power--;				res->nh_sel = nhsel;				spin_unlock_bh(&dn_fib_multipath_lock);				return;			}		}	} endfor_nexthops(fi);	res->nh_sel = 0;	spin_unlock_bh(&dn_fib_multipath_lock);}/* * Punt to user via netlink for example, but for now * we just drop it. */int dn_fib_rt_message(struct sk_buff *skb){	kfree_skb(skb);	return 0;}static int dn_fib_check_attr(struct rtmsg *r, struct rtattr **rta){	int i;	for(i = 1; i <= RTA_MAX; i++) {		struct rtattr *attr = rta[i-1];		if (attr) {			if (RTA_PAYLOAD(attr) < 4 && RTA_PAYLOAD(attr) != 2)				return -EINVAL;			if (i != RTA_MULTIPATH && i != RTA_METRICS)				rta[i-1] = (struct rtattr *)RTA_DATA(attr);		}	}	return 0;}int dn_fib_rtm_delroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg){	struct dn_fib_table *tb;	struct rtattr **rta = arg;	struct rtmsg *r = NLMSG_DATA(nlh);	if (dn_fib_check_attr(r, rta))		return -EINVAL;	tb = dn_fib_get_table(r->rtm_table, 0);	if (tb)		return tb->delete(tb, r, (struct dn_kern_rta *)rta, nlh, &NETLINK_CB(skb));	return -ESRCH;}int dn_fib_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg){	struct dn_fib_table *tb;	struct rtattr **rta = arg;	struct rtmsg *r = NLMSG_DATA(nlh);	if (dn_fib_check_attr(r, rta))		return -EINVAL;	tb = dn_fib_get_table(r->rtm_table, 1);	if (tb) 		return tb->insert(tb, r, (struct dn_kern_rta *)rta, nlh, &NETLINK_CB(skb));	return -ENOBUFS;}int dn_fib_dump(struct sk_buff *skb, struct netlink_callback *cb){	int t;	int s_t;	struct dn_fib_table *tb;	if (NLMSG_PAYLOAD(cb->nlh, 0) >= sizeof(struct rtmsg) &&		((struct rtmsg *)NLMSG_DATA(cb->nlh))->rtm_flags&RTM_F_CLONED)			return dn_cache_dump(skb, cb);	s_t = cb->args[0];	if (s_t == 0)		s_t = cb->args[0] = RT_MIN_TABLE;	for(t = s_t; t <= RT_TABLE_MAX; t++) {		if (t < s_t)			continue;		if (t > s_t)			memset(&cb->args[1], 0, sizeof(cb->args)-sizeof(int));		tb = dn_fib_get_table(t, 0);		if (tb == NULL)			continue;		if (tb->dump(tb, skb, cb) < 0)			break;	}	cb->args[0] = t;	return skb->len;}static void fib_magic(int cmd, int type, __u16 dst, int dst_len, struct dn_ifaddr *ifa){	struct dn_fib_table *tb;	struct {		struct nlmsghdr nlh;		struct rtmsg rtm;	} req;	struct dn_kern_rta rta;	memset(&req.rtm, 0, sizeof(req.rtm));	memset(&rta, 0, sizeof(rta));	if (type == RTN_UNICAST)		tb = dn_fib_get_table(RT_MIN_TABLE, 1);	else		tb = dn_fib_get_table(RT_TABLE_LOCAL, 1);	if (tb == NULL)		return;	req.nlh.nlmsg_len = sizeof(req);	req.nlh.nlmsg_type = cmd;	req.nlh.nlmsg_flags = NLM_F_REQUEST|NLM_F_CREATE|NLM_F_APPEND;	req.nlh.nlmsg_pid = 0;	req.nlh.nlmsg_seq = 0;	req.rtm.rtm_dst_len = dst_len;	req.rtm.rtm_table = tb->n;	req.rtm.rtm_protocol = RTPROT_KERNEL;	req.rtm.rtm_scope = (type != RTN_LOCAL ? RT_SCOPE_LINK : RT_SCOPE_HOST);	req.rtm.rtm_type = type;	rta.rta_dst = &dst;	rta.rta_prefsrc = &ifa->ifa_local;	rta.rta_oif = &ifa->ifa_dev->dev->ifindex;	if (cmd == RTM_NEWROUTE)		tb->insert(tb, &req.rtm, &rta, &req.nlh, NULL);	else		tb->delete(tb, &req.rtm, &rta, &req.nlh, NULL);}static void dn_fib_add_ifaddr(struct dn_ifaddr *ifa){	fib_magic(RTM_NEWROUTE, RTN_LOCAL, ifa->ifa_local, 16, ifa);#if 0	if (!(dev->flags&IFF_UP))		return;	/* In the future, we will want to add default routes here */#endif}static void dn_fib_del_ifaddr(struct dn_ifaddr *ifa){	int found_it = 0;	struct net_device *dev;	struct dn_dev *dn_db;	struct dn_ifaddr *ifa2;	ASSERT_RTNL();	/* Scan device list */	read_lock(&dev_base_lock);	for(dev = dev_base; dev; dev = dev->next) {		dn_db = dev->dn_ptr;		if (dn_db == NULL)			continue;		for(ifa2 = dn_db->ifa_list; ifa2; ifa2 = ifa2->ifa_next) {			if (ifa2->ifa_local == ifa->ifa_local) {				found_it = 1;				break;			}		}	}	read_unlock(&dev_base_lock);	if (found_it == 0) {		fib_magic(RTM_DELROUTE, RTN_LOCAL, ifa->ifa_local, 16, ifa);		if (dnet_addr_type(ifa->ifa_local) != RTN_LOCAL) {			if (dn_fib_sync_down(ifa->ifa_local, NULL, 0))				dn_fib_flush();		}	}}static void dn_fib_disable_addr(struct net_device *dev, int force){	if (dn_fib_sync_down(0, dev, force))		dn_fib_flush();	dn_rt_cache_flush(0);	neigh_ifdown(&dn_neigh_table, dev);}static int dn_fib_dnaddr_event(struct notifier_block *this, unsigned long event, void *ptr){	struct dn_ifaddr *ifa = (struct dn_ifaddr *)ptr;	switch(event) {		case NETDEV_UP:			dn_fib_add_ifaddr(ifa);			dn_fib_sync_up(ifa->ifa_dev->dev);			dn_rt_cache_flush(-1);			break;		case NETDEV_DOWN:			dn_fib_del_ifaddr(ifa);			if (ifa->ifa_dev && ifa->ifa_dev->ifa_list == NULL) {				dn_fib_disable_addr(ifa->ifa_dev->dev, 1);			} else {				dn_rt_cache_flush(-1);			}			break;	}	return NOTIFY_DONE;}int dn_fib_sync_down(dn_address local, struct net_device *dev, int force){        int ret = 0;        int scope = RT_SCOPE_NOWHERE;        if (force)                scope = -1;        for_fib_info() {                /*                  * This makes no sense for DECnet.... we will almost                 * certainly have more than one local address the same                 * over all our interfaces. It needs thinking about                 * some more.                 */                if (local && fi->fib_prefsrc == local) {                        fi->fib_flags |= RTNH_F_DEAD;                        ret++;                } else if (dev && fi->fib_nhs) {                        int dead = 0;                        change_nexthops(fi) {                                if (nh->nh_flags&RTNH_F_DEAD)                                        dead++;                                else if (nh->nh_dev == dev &&                                                nh->nh_scope != scope) {					spin_lock_bh(&dn_fib_multipath_lock);                                        nh->nh_flags |= RTNH_F_DEAD;                                        fi->fib_power -= nh->nh_power;                                        nh->nh_power = 0;					spin_unlock_bh(&dn_fib_multipath_lock);                                        dead++;                                }                        } endfor_nexthops(fi)                        if (dead == fi->fib_nhs) {                                fi->fib_flags |= RTNH_F_DEAD;                                ret++;                        }                }        } endfor_fib_info();        return ret;}int dn_fib_sync_up(struct net_device *dev){        int ret = 0;        if (!(dev->flags&IFF_UP))                return 0;        for_fib_info() {                int alive = 0;                change_nexthops(fi) {                        if (!(nh->nh_flags&RTNH_F_DEAD)) {                                alive++;                                continue;                        }                        if (nh->nh_dev == NULL || !(nh->nh_dev->flags&IFF_UP))                                continue;                        if (nh->nh_dev != dev || dev->dn_ptr == NULL)                                continue;                        alive++;			spin_lock_bh(&dn_fib_multipath_lock);                        nh->nh_power = 0;                        nh->nh_flags &= ~RTNH_F_DEAD;			spin_unlock_bh(&dn_fib_multipath_lock);                } endfor_nexthops(fi);                if (alive > 0) {                        fi->fib_flags &= ~RTNH_F_DEAD;                        ret++;                }        } endfor_fib_info();        return ret;}void dn_fib_flush(void){        int flushed = 0;        struct dn_fib_table *tb;        int id;        for(id = RT_TABLE_MAX; id > 0; id--) {                if ((tb = dn_fib_get_table(id, 0)) == NULL)                        continue;                flushed += tb->flush(tb);        }        if (flushed)                dn_rt_cache_flush(-1);}static struct notifier_block dn_fib_dnaddr_notifier = {	.notifier_call = dn_fib_dnaddr_event,};void __exit dn_fib_cleanup(void){	dn_fib_table_cleanup();	dn_fib_rules_cleanup();	unregister_dnaddr_notifier(&dn_fib_dnaddr_notifier);}void __init dn_fib_init(void){	dn_fib_table_init();	dn_fib_rules_init();	register_dnaddr_notifier(&dn_fib_dnaddr_notifier);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -