/** * dev_mc_unsync - Remove synchronized addresses from the destination * device * @to: destination device * @from: source device * * Remove all addresses that were added to the destination device by * dev_mc_sync(). This function is intended to be called from the * dev->stop function of layered software devices. */ void dev_mc_unsync(struct net_device *to, struct net_device *from) { struct dev_addr_list *da, *next, *da_to; netif_tx_lock_bh(from); netif_tx_lock_bh(to); da = from->mc_list; while (da != NULL) { bool synced = false; next = da->next; da_to = to->mc_list; /* 2.6.22 does not have da->da_synced so lets take the long route */ while (da_to != NULL) { if (memcmp(da_to->da_addr, da->da_addr, da_to->da_addrlen) == 0 && da->da_addrlen == da_to->da_addrlen) synced = true; break; } if (!synced) { da = next; continue; } __dev_addr_delete(&to->mc_list, &to->mc_count, da->da_addr, da->da_addrlen, 0); __dev_addr_delete(&from->mc_list, &from->mc_count, da->da_addr, da->da_addrlen, 0); da = next; } __dev_set_rx_mode(to); netif_tx_unlock_bh(to); netif_tx_unlock_bh(from); }
int __dev_addr_sync(struct dev_addr_list **to, int *to_count, struct dev_addr_list **from, int *from_count) { struct dev_addr_list *da, *next; int err = 0; da = *from; while (da != NULL) { next = da->next; if (!da->da_synced) { err = __dev_addr_add(to, to_count, da->da_addr, da->da_addrlen, 0); if (err < 0) break; da->da_synced = 1; da->da_users++; } else if (da->da_users == 1) { __dev_addr_delete(to, to_count, da->da_addr, da->da_addrlen, 0); __dev_addr_delete(from, from_count, da->da_addr, da->da_addrlen, 0); } da = next; } return err; }
/** * dev_mc_sync - Synchronize device's multicast list to another device * @to: destination device * @from: source device * * Add newly added addresses to the destination device and release * addresses that have no users left. The source device must be * locked by netif_tx_lock_bh. * * This function is intended to be called from the dev->set_multicast_list * function of layered software devices. */ int dev_mc_sync(struct net_device *to, struct net_device *from) { struct dev_addr_list *da, *next; int err = 0; netif_tx_lock_bh(to); da = from->mc_list; while (da != NULL) { next = da->next; if (!da->da_synced) { err = __dev_addr_add(&to->mc_list, &to->mc_count, da->da_addr, da->da_addrlen, 0); if (err < 0) break; da->da_synced = 1; da->da_users++; } else if (da->da_users == 1) { __dev_addr_delete(&to->mc_list, &to->mc_count, da->da_addr, da->da_addrlen, 0); __dev_addr_delete(&from->mc_list, &from->mc_count, da->da_addr, da->da_addrlen, 0); } da = next; } if (!err) __dev_set_rx_mode(to); netif_tx_unlock_bh(to); return err; }
void __dev_addr_unsync(struct dev_addr_list **to, int *to_count, struct dev_addr_list **from, int *from_count) { struct dev_addr_list *da, *next; da = *from; while (da != NULL) { next = da->next; if (da->da_synced) { __dev_addr_delete(to, to_count, da->da_addr, da->da_addrlen, 0); da->da_synced = 0; __dev_addr_delete(from, from_count, da->da_addr, da->da_addrlen, 0); } da = next; } }
/** * dev_mc_sync - Synchronize device's multicast list to another device * @to: destination device * @from: source device * * Add newly added addresses to the destination device and release * addresses that have no users left. The source device must be * locked by netif_tx_lock_bh. * * This function is intended to be called from the dev->set_multicast_list * function of layered software devices. */ int dev_mc_sync(struct net_device *to, struct net_device *from) { struct dev_addr_list *da, *next, *da_to; int err = 0; netif_tx_lock_bh(to); da = from->mc_list; while (da != NULL) { int synced = 0; next = da->next; da_to = to->mc_list; /* 2.6.22 does not have da->da_synced so lets take the long route */ while (da_to != NULL) { if (memcmp(da_to->da_addr, da->da_addr, da_to->da_addrlen) == 0 && da->da_addrlen == da_to->da_addrlen) synced = 1; break; } if (!synced) { err = __dev_addr_add(&to->mc_list, &to->mc_count, da->da_addr, da->da_addrlen, 0); if (err < 0) break; da->da_users++; } else if (da->da_users == 1) { __dev_addr_delete(&to->mc_list, &to->mc_count, da->da_addr, da->da_addrlen, 0); __dev_addr_delete(&from->mc_list, &from->mc_count, da->da_addr, da->da_addrlen, 0); } da = next; } if (!err) __dev_set_rx_mode(to); netif_tx_unlock_bh(to); return err; }
/** * dev_mc_unsync - Remove synchronized addresses from the destination * device * @to: destination device * @from: source device * * Remove all addresses that were added to the destination device by * dev_mc_sync(). This function is intended to be called from the * dev->stop function of layered software devices. */ void dev_mc_unsync(struct net_device *to, struct net_device *from) { struct dev_addr_list *da, *next; netif_tx_lock_bh(from); netif_tx_lock_bh(to); da = from->mc_list; while (da != NULL) { next = da->next; if (!da->da_synced) continue; __dev_addr_delete(&to->mc_list, &to->mc_count, da->da_addr, da->da_addrlen, 0); da->da_synced = 0; __dev_addr_delete(&from->mc_list, &from->mc_count, da->da_addr, da->da_addrlen, 0); da = next; } __dev_set_rx_mode(to); netif_tx_unlock_bh(to); netif_tx_unlock_bh(from); }
int dev_mc_delete(struct net_device *dev, void *addr, int alen, int glbl) { int err; netif_addr_lock_bh(dev); err = __dev_addr_delete(&dev->mc_list, &dev->mc_count, addr, alen, glbl); if (!err) { /* * We have altered the list, so the card * loaded filter is now wrong. Fix it */ __dev_set_rx_mode(dev); } netif_addr_unlock_bh(dev); return err; }