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; }
int dev_mc_add(struct net_device *dev, void *addr, int alen, int glbl) { int err; netif_tx_lock_bh(dev); err = __dev_addr_add(&dev->mc_list, &dev->mc_count, addr, alen, glbl); if (!err) __dev_set_rx_mode(dev); netif_tx_unlock_bh(dev); 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, *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; }