static int mif6_delete(int vifi) { struct mif_device *v; struct net_device *dev; if (vifi < 0 || vifi >= maxvif) return -EADDRNOTAVAIL; v = &vif6_table[vifi]; write_lock_bh(&mrt_lock); dev = v->dev; v->dev = NULL; if (!dev) { write_unlock_bh(&mrt_lock); return -EADDRNOTAVAIL; } #ifdef CONFIG_IPV6_PIMSM_V2 if (vifi == reg_vif_num) reg_vif_num = -1; #endif if (vifi + 1 == maxvif) { int tmp; for (tmp = vifi - 1; tmp >= 0; tmp--) { if (MIF_EXISTS(tmp)) break; } maxvif = tmp + 1; } write_unlock_bh(&mrt_lock); dev_set_allmulti(dev, -1); if (v->flags & MIFF_REGISTER) unregister_netdevice(dev); dev_put(dev); return 0; }
static void ip6mr_update_thresholds(struct mfc6_cache *cache, unsigned char *ttls) { int vifi; struct net *net = mfc6_net(cache); cache->mfc_un.res.minvif = MAXMIFS; cache->mfc_un.res.maxvif = 0; memset(cache->mfc_un.res.ttls, 255, MAXMIFS); for (vifi = 0; vifi < net->ipv6.maxvif; vifi++) { if (MIF_EXISTS(net, vifi) && ttls[vifi] && ttls[vifi] < 255) { cache->mfc_un.res.ttls[vifi] = ttls[vifi]; if (cache->mfc_un.res.minvif > vifi) cache->mfc_un.res.minvif = vifi; if (cache->mfc_un.res.maxvif <= vifi) cache->mfc_un.res.maxvif = vifi + 1; } } }
static int ipmr_mfc_seq_show(struct seq_file *seq, void *v) { int n; struct net *net = seq_file_net(seq); if (v == SEQ_START_TOKEN) { seq_puts(seq, "Group " "Origin " "Iif Pkts Bytes Wrong Oifs\n"); } else { const struct mfc6_cache *mfc = v; const struct ipmr_mfc_iter *it = seq->private; seq_printf(seq, "%pI6 %pI6 %-3hd", &mfc->mf6c_mcastgrp, &mfc->mf6c_origin, mfc->mf6c_parent); if (it->cache != &mfc_unres_queue) { seq_printf(seq, " %8lu %8lu %8lu", mfc->mfc_un.res.pkt, mfc->mfc_un.res.bytes, mfc->mfc_un.res.wrong_if); for (n = mfc->mfc_un.res.minvif; n < mfc->mfc_un.res.maxvif; n++) { if (MIF_EXISTS(net, n) && mfc->mfc_un.res.ttls[n] < 255) seq_printf(seq, " %2d:%-3d", n, mfc->mfc_un.res.ttls[n]); } } else { /* unresolved mfc_caches don't contain * pkt, bytes and wrong_if values */ seq_printf(seq, " %8lu %8lu %8lu", 0ul, 0ul, 0ul); } seq_putc(seq, '\n'); } return 0; }
static int mif6_add(struct mif6ctl *vifc, int mrtsock) { int vifi = vifc->mif6c_mifi; struct mif_device *v = &vif6_table[vifi]; struct net_device *dev; /* Is vif busy ? */ if (MIF_EXISTS(vifi)) return -EADDRINUSE; switch (vifc->mif6c_flags) { #ifdef CONFIG_IPV6_PIMSM_V2 case MIFF_REGISTER: /* * Special Purpose VIF in PIM * All the packets will be sent to the daemon */ if (reg_vif_num >= 0) return -EADDRINUSE; dev = ip6mr_reg_vif(); if (!dev) return -ENOBUFS; break; #endif case 0: dev = dev_get_by_index(vifc->mif6c_pifi); if (!dev) return -EADDRNOTAVAIL; dev_put(dev); break; default: return -EINVAL; } dev_set_allmulti(dev, 1); /* * Fill in the VIF structures */ v->rate_limit = vifc->vifc_rate_limit; v->flags = vifc->mif6c_flags; if (!mrtsock) v->flags |= VIFF_STATIC; v->threshold = vifc->vifc_threshold; v->bytes_in = 0; v->bytes_out = 0; v->pkt_in = 0; v->pkt_out = 0; v->link = dev->ifindex; if (v->flags & MIFF_REGISTER) v->link = dev->iflink; /* And finish update writing critical data */ write_lock_bh(&mrt_lock); dev_hold(dev); v->dev = dev; #ifdef CONFIG_IPV6_PIMSM_V2 if (v->flags & MIFF_REGISTER) reg_vif_num = vifi; #endif if (vifi + 1 > maxvif) maxvif = vifi + 1; write_unlock_bh(&mrt_lock); return 0; }