struct dev_addr_list    *next;
        u8                      da_addr[MAX_ADDR_LEN];
        u8                      da_addrlen;
+       u8                      da_synced;
        int                     da_users;
        int                     da_gusers;
 };
 extern int             dev_unicast_add(struct net_device *dev, void *addr, int alen);
 extern int             dev_mc_delete(struct net_device *dev, void *addr, int alen, int all);
 extern int             dev_mc_add(struct net_device *dev, void *addr, int alen, int newonly);
+extern int             dev_mc_sync(struct net_device *to, struct net_device *from);
+extern void            dev_mc_unsync(struct net_device *to, struct net_device *from);
 extern void            dev_mc_discard(struct net_device *dev);
 extern int             __dev_addr_delete(struct dev_addr_list **list, int *count, void *addr, int alen, int all);
 extern int             __dev_addr_add(struct dev_addr_list **list, int *count, void *addr, int alen, int newonly);
 
        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;
+       int err = 0;
+
+       netif_tx_lock_bh(to);
+       for (da = from->mc_list; da != NULL; da = 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);
+               }
+       }
+       if (!err)
+               __dev_set_rx_mode(to);
+       netif_tx_unlock_bh(to);
+
+       return err;
+}
+EXPORT_SYMBOL(dev_mc_sync);
+
+
+/**
+ *     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;
+
+       netif_tx_lock_bh(from);
+       netif_tx_lock_bh(to);
+
+       for (da = from->mc_list; da != NULL; da = 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);
+       }
+       __dev_set_rx_mode(to);
+
+       netif_tx_unlock_bh(to);
+       netif_tx_unlock_bh(from);
+}
+EXPORT_SYMBOL(dev_mc_unsync);
+
 /*
  *     Discard multicast list when a device is downed
  */