Lines Matching refs:mrt

58 	struct mr_table	*mrt;
61 /* Big lock, protecting vif table, mrt cache and mroute socket state.
88 static void ip6mr_free_table(struct mr_table *mrt);
90 static void ip6_mr_forward(struct net *net, struct mr_table *mrt,
93 static int ip6mr_cache_report(const struct mr_table *mrt, struct sk_buff *pkt,
95 static void mr6_netlink_event(struct mr_table *mrt, struct mfc6_cache *mfc,
97 static void mrt6msg_netlink_event(const struct mr_table *mrt, struct sk_buff *pkt);
102 static void mroute_clean_tables(struct mr_table *mrt, int flags);
106 #define ip6mr_for_each_table(mrt, net) \
107 list_for_each_entry_rcu(mrt, &net->ipv6.mr6_tables, list, \
112 struct mr_table *mrt)
116 if (!mrt)
120 ret = list_entry_rcu(mrt->list.next,
130 struct mr_table *mrt;
132 ip6mr_for_each_table(mrt, net) {
133 if (mrt->id == id)
134 return mrt;
140 struct mr_table **mrt)
156 *mrt = res.mrt;
164 struct mr_table *mrt;
180 mrt = ip6mr_get_table(rule->fr_net, arg->table);
181 if (!mrt)
183 res->mrt = mrt;
230 struct mr_table *mrt;
239 mrt = ip6mr_new_table(net, RT6_TABLE_DFLT);
240 if (IS_ERR(mrt)) {
241 err = PTR_ERR(mrt);
254 ip6mr_free_table(mrt);
263 struct mr_table *mrt, *next;
266 list_for_each_entry_safe(mrt, next, &net->ipv6.mr6_tables, list) {
267 list_del(&mrt->list);
268 ip6mr_free_table(mrt);
291 #define ip6mr_for_each_table(mrt, net) \
292 for (mrt = net->ipv6.mrt6; mrt; mrt = NULL)
295 struct mr_table *mrt)
297 if (!mrt)
308 struct mr_table **mrt)
310 *mrt = net->ipv6.mrt6;
316 struct mr_table *mrt;
318 mrt = ip6mr_new_table(net, RT6_TABLE_DFLT);
319 if (IS_ERR(mrt))
320 return PTR_ERR(mrt);
321 net->ipv6.mrt6 = mrt;
363 static void ip6mr_new_table_set(struct mr_table *mrt,
367 list_add_tail_rcu(&mrt->list, &net->ipv6.mr6_tables);
383 struct mr_table *mrt;
385 mrt = ip6mr_get_table(net, id);
386 if (mrt)
387 return mrt;
393 static void ip6mr_free_table(struct mr_table *mrt)
395 timer_shutdown_sync(&mrt->ipmr_expire_timer);
396 mroute_clean_tables(mrt, MRT6_FLUSH_MIFS | MRT6_FLUSH_MIFS_STATIC |
398 rhltable_destroy(&mrt->mfc_hash);
399 kfree(mrt);
412 struct mr_table *mrt;
414 mrt = ip6mr_get_table(net, RT6_TABLE_DFLT);
415 if (!mrt)
418 iter->mrt = mrt;
433 struct mr_table *mrt = iter->mrt;
448 vif - mrt->vif_table,
466 struct mr_table *mrt;
468 mrt = ip6mr_get_table(net, RT6_TABLE_DFLT);
469 if (!mrt)
472 return mr_mfc_seq_start(seq, pos, mrt, &mfc_unres_lock);
487 struct mr_table *mrt = it->mrt;
493 if (it->cache != &mrt->mfc_unres_queue) {
500 if (VIF_EXISTS(mrt, n) &&
533 struct mr_table *mrt;
561 if (ip6mr_fib_lookup(net, &fl6, &mrt) < 0)
565 reg_vif_num = READ_ONCE(mrt->mroute_reg_vif_num);
567 reg_dev = vif_dev_read(&mrt->vif_table[reg_vif_num]);
598 struct mr_table *mrt;
608 if (ip6mr_fib_lookup(net, &fl6, &mrt) < 0)
614 ip6mr_cache_report(mrt, skb, READ_ONCE(mrt->mroute_reg_vif_num),
646 static struct net_device *ip6mr_reg_vif(struct net *net, struct mr_table *mrt)
651 if (mrt->id == RT6_TABLE_DFLT)
654 sprintf(name, "pim6reg%u", mrt->id);
699 static int mif6_delete(struct mr_table *mrt, int vifi, int notify,
706 if (vifi < 0 || vifi >= mrt->maxvif)
709 v = &mrt->vif_table[vifi];
715 call_ip6mr_vif_entry_notifiers(read_pnet(&mrt->net),
717 vifi, mrt->id);
722 if (vifi == mrt->mroute_reg_vif_num) {
724 WRITE_ONCE(mrt->mroute_reg_vif_num, -1);
728 if (vifi + 1 == mrt->maxvif) {
731 if (VIF_EXISTS(mrt, tmp))
734 WRITE_ONCE(mrt->maxvif, tmp + 1);
772 static void ip6mr_destroy_unres(struct mr_table *mrt, struct mfc6_cache *c)
774 struct net *net = read_pnet(&mrt->net);
777 atomic_dec(&mrt->cache_resolve_queue_len);
798 static void ipmr_do_expire_process(struct mr_table *mrt)
804 list_for_each_entry_safe(c, next, &mrt->mfc_unres_queue, list) {
814 mr6_netlink_event(mrt, (struct mfc6_cache *)c, RTM_DELROUTE);
815 ip6mr_destroy_unres(mrt, (struct mfc6_cache *)c);
818 if (!list_empty(&mrt->mfc_unres_queue))
819 mod_timer(&mrt->ipmr_expire_timer, jiffies + expires);
824 struct mr_table *mrt = from_timer(mrt, t, ipmr_expire_timer);
827 mod_timer(&mrt->ipmr_expire_timer, jiffies + 1);
831 if (!list_empty(&mrt->mfc_unres_queue))
832 ipmr_do_expire_process(mrt);
839 static void ip6mr_update_thresholds(struct mr_table *mrt,
849 for (vifi = 0; vifi < mrt->maxvif; vifi++) {
850 if (VIF_EXISTS(mrt, vifi) &&
862 static int mif6_add(struct net *net, struct mr_table *mrt,
866 struct vif_device *v = &mrt->vif_table[vifi];
872 if (VIF_EXISTS(mrt, vifi))
882 if (mrt->mroute_reg_vif_num >= 0)
884 dev = ip6mr_reg_vif(net, mrt);
928 WRITE_ONCE(mrt->mroute_reg_vif_num, vifi);
930 if (vifi + 1 > mrt->maxvif)
931 WRITE_ONCE(mrt->maxvif, vifi + 1);
934 v, dev, vifi, mrt->id);
938 static struct mfc6_cache *ip6mr_cache_find(struct mr_table *mrt,
947 return mr_mfc_find(mrt, &arg);
951 static struct mfc6_cache *ip6mr_cache_find_any(struct mr_table *mrt,
961 return mr_mfc_find_any_parent(mrt, mifi);
962 return mr_mfc_find_any(mrt, mifi, &arg);
967 ip6mr_cache_find_parent(struct mr_table *mrt,
977 return mr_mfc_find_parent(mrt, &arg, parent);
1007 static void ip6mr_cache_resolve(struct net *net, struct mr_table *mrt,
1021 if (mr_fill_mroute(mrt, skb, &c->_c,
1033 ip6_mr_forward(net, mrt, skb->dev, skb, c);
1045 static int ip6mr_cache_report(const struct mr_table *mrt, struct sk_buff *pkt,
1086 msg->im6_mif = READ_ONCE(mrt->mroute_reg_vif_num);
1121 mroute6_sk = rcu_dereference(mrt->mroute_sk);
1127 mrt6msg_netlink_event(mrt, skb);
1141 static int ip6mr_cache_unresolved(struct mr_table *mrt, mifi_t mifi,
1149 list_for_each_entry(c, &mrt->mfc_unres_queue, _c.list) {
1178 err = ip6mr_cache_report(mrt, skb, mifi, MRT6MSG_NOCACHE);
1190 atomic_inc(&mrt->cache_resolve_queue_len);
1191 list_add(&c->_c.list, &mrt->mfc_unres_queue);
1192 mr6_netlink_event(mrt, c, RTM_NEWROUTE);
1194 ipmr_do_expire_process(mrt);
1218 static int ip6mr_mfc_delete(struct mr_table *mrt, struct mf6cctl *mfc,
1225 c = ip6mr_cache_find_parent(mrt, &mfc->mf6cc_origin.sin6_addr,
1230 rhltable_remove(&mrt->mfc_hash, &c->_c.mnode, ip6mr_rht_params);
1233 call_ip6mr_mfc_entry_notifiers(read_pnet(&mrt->net),
1234 FIB_EVENT_ENTRY_DEL, c, mrt->id);
1235 mr6_netlink_event(mrt, c, RTM_DELROUTE);
1245 struct mr_table *mrt;
1252 ip6mr_for_each_table(mrt, net) {
1253 v = &mrt->vif_table[0];
1254 for (ct = 0; ct < mrt->maxvif; ct++, v++) {
1256 mif6_delete(mrt, ct, 1, NULL);
1425 static int ip6mr_mfc_add(struct net *net, struct mr_table *mrt,
1445 c = ip6mr_cache_find_parent(mrt, &mfc->mf6cc_origin.sin6_addr,
1451 ip6mr_update_thresholds(mrt, &c->_c, ttls);
1456 c, mrt->id);
1457 mr6_netlink_event(mrt, c, RTM_NEWROUTE);
1472 ip6mr_update_thresholds(mrt, &c->_c, ttls);
1476 err = rhltable_insert_key(&mrt->mfc_hash, &c->cmparg, &c->_c.mnode,
1483 list_add_tail_rcu(&c->_c.list, &mrt->mfc_cache_list);
1490 list_for_each_entry(_uc, &mrt->mfc_unres_queue, list) {
1495 atomic_dec(&mrt->cache_resolve_queue_len);
1500 if (list_empty(&mrt->mfc_unres_queue))
1501 del_timer(&mrt->ipmr_expire_timer);
1505 ip6mr_cache_resolve(net, mrt, uc, c);
1509 c, mrt->id);
1510 mr6_netlink_event(mrt, c, RTM_NEWROUTE);
1518 static void mroute_clean_tables(struct mr_table *mrt, int flags)
1526 for (i = 0; i < mrt->maxvif; i++) {
1527 if (((mrt->vif_table[i].flags & VIFF_STATIC) &&
1529 (!(mrt->vif_table[i].flags & VIFF_STATIC) && !(flags & MRT6_FLUSH_MIFS)))
1531 mif6_delete(mrt, i, 0, &list);
1538 list_for_each_entry_safe(c, tmp, &mrt->mfc_cache_list, list) {
1542 rhltable_remove(&mrt->mfc_hash, &c->mnode, ip6mr_rht_params);
1544 call_ip6mr_mfc_entry_notifiers(read_pnet(&mrt->net),
1546 (struct mfc6_cache *)c, mrt->id);
1547 mr6_netlink_event(mrt, (struct mfc6_cache *)c, RTM_DELROUTE);
1553 if (atomic_read(&mrt->cache_resolve_queue_len) != 0) {
1555 list_for_each_entry_safe(c, tmp, &mrt->mfc_unres_queue, list) {
1557 mr6_netlink_event(mrt, (struct mfc6_cache *)c,
1559 ip6mr_destroy_unres(mrt, (struct mfc6_cache *)c);
1566 static int ip6mr_sk_init(struct mr_table *mrt, struct sock *sk)
1573 if (rtnl_dereference(mrt->mroute_sk)) {
1576 rcu_assign_pointer(mrt->mroute_sk, sk);
1596 struct mr_table *mrt;
1608 ip6mr_for_each_table(mrt, net) {
1609 if (sk == rtnl_dereference(mrt->mroute_sk)) {
1611 RCU_INIT_POINTER(mrt->mroute_sk, NULL);
1623 mroute_clean_tables(mrt, MRT6_FLUSH_MIFS | MRT6_FLUSH_MFC);
1635 struct mr_table *mrt;
1642 if (ip6mr_fib_lookup(net, &fl6, &mrt) < 0)
1645 return rcu_access_pointer(mrt->mroute_sk);
1664 struct mr_table *mrt;
1670 mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT);
1671 if (!mrt)
1675 if (sk != rcu_access_pointer(mrt->mroute_sk) &&
1685 return ip6mr_sk_init(mrt, sk);
1698 ret = mif6_add(net, mrt, &vif,
1699 sk == rtnl_dereference(mrt->mroute_sk));
1709 ret = mif6_delete(mrt, mifi, 0, NULL);
1731 ret = ip6mr_mfc_delete(mrt, &mfc, parent);
1733 ret = ip6mr_mfc_add(net, mrt, &mfc,
1735 rtnl_dereference(mrt->mroute_sk),
1749 mroute_clean_tables(mrt, flags);
1765 mrt->mroute_do_assert = v;
1784 if (v != mrt->mroute_do_pim) {
1785 mrt->mroute_do_pim = v;
1786 mrt->mroute_do_assert = v;
1787 mrt->mroute_do_wrvifwhole = do_wrmifwhole;
1806 if (sk == rcu_access_pointer(mrt->mroute_sk))
1811 mrt = ip6mr_new_table(net, v);
1812 if (IS_ERR(mrt))
1813 ret = PTR_ERR(mrt);
1839 struct mr_table *mrt;
1845 mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT);
1846 if (!mrt)
1855 val = mrt->mroute_do_pim;
1859 val = mrt->mroute_do_assert;
1889 struct mr_table *mrt;
1891 mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT);
1892 if (!mrt)
1898 if (vr->mifi >= mrt->maxvif)
1900 vr->mifi = array_index_nospec(vr->mifi, mrt->maxvif);
1902 vif = &mrt->vif_table[vr->mifi];
1903 if (VIF_EXISTS(mrt, vr->mifi)) {
1917 c = ip6mr_cache_find(mrt, &sr->src.sin6_addr,
1957 struct mr_table *mrt;
1959 mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT);
1960 if (!mrt)
1967 if (vr.mifi >= mrt->maxvif)
1969 vr.mifi = array_index_nospec(vr.mifi, mrt->maxvif);
1971 vif = &mrt->vif_table[vr.mifi];
1972 if (VIF_EXISTS(mrt, vr.mifi)) {
1990 c = ip6mr_cache_find(mrt, &sr.src.sin6_addr, &sr.grp.sin6_addr);
2020 static int ip6mr_forward2(struct net *net, struct mr_table *mrt,
2023 struct vif_device *vif = &mrt->vif_table[vifi];
2039 ip6mr_cache_report(mrt, skb, vifi, MRT6MSG_WHOLEPKT);
2095 static int ip6mr_find_vif(struct mr_table *mrt, struct net_device *dev)
2100 for (ct = READ_ONCE(mrt->maxvif) - 1; ct >= 0; ct--) {
2101 if (rcu_access_pointer(mrt->vif_table[ct].dev) == dev)
2108 static void ip6_mr_forward(struct net *net, struct mr_table *mrt,
2114 int true_vifi = ip6mr_find_vif(mrt, dev);
2127 cache_proxy = mr_mfc_find_any_parent(mrt, vif);
2136 if (rcu_access_pointer(mrt->vif_table[vif].dev) != dev) {
2139 if (true_vifi >= 0 && mrt->mroute_do_assert &&
2145 (mrt->mroute_do_pim ||
2151 ip6mr_cache_report(mrt, skb, true_vifi, MRT6MSG_WRONGMIF);
2152 if (mrt->mroute_do_wrvifwhole)
2153 ip6mr_cache_report(mrt, skb, true_vifi,
2160 WRITE_ONCE(mrt->vif_table[vif].pkt_in,
2161 mrt->vif_table[vif].pkt_in + 1);
2162 WRITE_ONCE(mrt->vif_table[vif].bytes_in,
2163 mrt->vif_table[vif].bytes_in + skb->len);
2191 ip6mr_forward2(net, mrt, skb2, psend);
2198 ip6mr_forward2(net, mrt, skb, psend);
2215 struct mr_table *mrt;
2235 err = ip6mr_fib_lookup(net, &fl6, &mrt);
2241 cache = ip6mr_cache_find(mrt,
2244 int vif = ip6mr_find_vif(mrt, dev);
2247 cache = ip6mr_cache_find_any(mrt,
2258 vif = ip6mr_find_vif(mrt, dev);
2260 int err = ip6mr_cache_unresolved(mrt, vif, skb, dev);
2268 ip6_mr_forward(net, mrt, dev, skb, cache);
2277 struct mr_table *mrt;
2281 mrt = ip6mr_get_table(net, RT6_TABLE_DFLT);
2282 if (!mrt)
2286 cache = ip6mr_cache_find(mrt, &rt->rt6i_src.addr, &rt->rt6i_dst.addr);
2288 int vif = ip6mr_find_vif(mrt, skb->dev);
2291 cache = ip6mr_cache_find_any(mrt, &rt->rt6i_dst.addr,
2302 if (!dev || (vif = ip6mr_find_vif(mrt, dev)) < 0) {
2332 err = ip6mr_cache_unresolved(mrt, vif, skb2, dev);
2338 err = mr_fill_mroute(mrt, skb, &cache->_c, rtm);
2343 static int ip6mr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
2360 rtm->rtm_table = mrt->id;
2361 if (nla_put_u32(skb, RTA_TABLE, mrt->id))
2374 err = mr_fill_mroute(mrt, skb, &c->_c, rtm);
2387 static int _ip6mr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
2391 return ip6mr_fill_mroute(mrt, skb, portid, seq, (struct mfc6_cache *)c,
2416 static void mr6_netlink_event(struct mr_table *mrt, struct mfc6_cache *mfc,
2419 struct net *net = read_pnet(&mrt->net);
2423 skb = nlmsg_new(mr6_msgsize(mfc->_c.mfc_parent >= MAXMIFS, mrt->maxvif),
2428 err = ip6mr_fill_mroute(mrt, skb, 0, 0, mfc, cmd, 0);
2458 static void mrt6msg_netlink_event(const struct mr_table *mrt, struct sk_buff *pkt)
2460 struct net *net = read_pnet(&mrt->net);
2551 struct mr_table *mrt;
2566 mrt = ip6mr_get_table(net, tableid ?: RT_TABLE_DEFAULT);
2567 if (!mrt) {
2574 cache = ip6mr_cache_find(mrt, &src, &grp);
2581 skb = nlmsg_new(mr6_msgsize(false, mrt->maxvif), GFP_KERNEL);
2585 err = ip6mr_fill_mroute(mrt, skb, NETLINK_CB(in_skb).portid,
2609 struct mr_table *mrt;
2611 mrt = ip6mr_get_table(sock_net(skb->sk), filter.table_id);
2612 if (!mrt) {
2619 err = mr_table_dump(mrt, skb, cb, _ip6mr_fill_mroute,