aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2007-06-27 04:28:10 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-07-11 01:15:56 -0400
commit4417da668c0021903464f92db278ddae348e0299 (patch)
treea4330cbc2e69a5714fee0a04bcfbabe97109de46
parent3fba5a8b1e3df2384b90493538161e83cf15dd5f (diff)
[NET]: dev: secondary unicast address support
Add support for configuring secondary unicast addresses on network devices. To support this devices capable of filtering multiple unicast addresses need to change their set_multicast_list function to configure unicast filters as well and assign it to dev->set_rx_mode instead of dev->set_multicast_list. Other devices are put into promiscous mode when secondary unicast addresses are present. Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/netdevice.h12
-rw-r--r--net/core/dev.c144
-rw-r--r--net/core/dev_mcast.c37
3 files changed, 139 insertions, 54 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 9e114e77e54d..2c0cc19edfb2 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -397,6 +397,9 @@ struct net_device
397 unsigned char addr_len; /* hardware address length */ 397 unsigned char addr_len; /* hardware address length */
398 unsigned short dev_id; /* for shared network cards */ 398 unsigned short dev_id; /* for shared network cards */
399 399
400 struct dev_addr_list *uc_list; /* Secondary unicast mac addresses */
401 int uc_count; /* Number of installed ucasts */
402 int uc_promisc;
400 struct dev_addr_list *mc_list; /* Multicast mac addresses */ 403 struct dev_addr_list *mc_list; /* Multicast mac addresses */
401 int mc_count; /* Number of installed mcasts */ 404 int mc_count; /* Number of installed mcasts */
402 int promiscuity; 405 int promiscuity;
@@ -502,6 +505,8 @@ struct net_device
502 void *saddr, 505 void *saddr,
503 unsigned len); 506 unsigned len);
504 int (*rebuild_header)(struct sk_buff *skb); 507 int (*rebuild_header)(struct sk_buff *skb);
508#define HAVE_SET_RX_MODE
509 void (*set_rx_mode)(struct net_device *dev);
505#define HAVE_MULTICAST 510#define HAVE_MULTICAST
506 void (*set_multicast_list)(struct net_device *dev); 511 void (*set_multicast_list)(struct net_device *dev);
507#define HAVE_SET_MAC_ADDR 512#define HAVE_SET_MAC_ADDR
@@ -1008,8 +1013,11 @@ extern struct net_device *alloc_netdev(int sizeof_priv, const char *name,
1008 void (*setup)(struct net_device *)); 1013 void (*setup)(struct net_device *));
1009extern int register_netdev(struct net_device *dev); 1014extern int register_netdev(struct net_device *dev);
1010extern void unregister_netdev(struct net_device *dev); 1015extern void unregister_netdev(struct net_device *dev);
1011/* Functions used for multicast support */ 1016/* Functions used for secondary unicast and multicast support */
1012extern void dev_mc_upload(struct net_device *dev); 1017extern void dev_set_rx_mode(struct net_device *dev);
1018extern void __dev_set_rx_mode(struct net_device *dev);
1019extern int dev_unicast_delete(struct net_device *dev, void *addr, int alen);
1020extern int dev_unicast_add(struct net_device *dev, void *addr, int alen);
1013extern int dev_mc_delete(struct net_device *dev, void *addr, int alen, int all); 1021extern int dev_mc_delete(struct net_device *dev, void *addr, int alen, int all);
1014extern int dev_mc_add(struct net_device *dev, void *addr, int alen, int newonly); 1022extern int dev_mc_add(struct net_device *dev, void *addr, int alen, int newonly);
1015extern void dev_mc_discard(struct net_device *dev); 1023extern void dev_mc_discard(struct net_device *dev);
diff --git a/net/core/dev.c b/net/core/dev.c
index 18759ccdf219..36e9bf8ec4af 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -942,7 +942,7 @@ int dev_open(struct net_device *dev)
942 /* 942 /*
943 * Initialize multicasting status 943 * Initialize multicasting status
944 */ 944 */
945 dev_mc_upload(dev); 945 dev_set_rx_mode(dev);
946 946
947 /* 947 /*
948 * Wakeup transmit queue engine 948 * Wakeup transmit queue engine
@@ -2498,17 +2498,7 @@ int netdev_set_master(struct net_device *slave, struct net_device *master)
2498 return 0; 2498 return 0;
2499} 2499}
2500 2500
2501/** 2501static void __dev_set_promiscuity(struct net_device *dev, int inc)
2502 * dev_set_promiscuity - update promiscuity count on a device
2503 * @dev: device
2504 * @inc: modifier
2505 *
2506 * Add or remove promiscuity from a device. While the count in the device
2507 * remains above zero the interface remains promiscuous. Once it hits zero
2508 * the device reverts back to normal filtering operation. A negative inc
2509 * value is used to drop promiscuity on the device.
2510 */
2511void dev_set_promiscuity(struct net_device *dev, int inc)
2512{ 2502{
2513 unsigned short old_flags = dev->flags; 2503 unsigned short old_flags = dev->flags;
2514 2504
@@ -2517,7 +2507,6 @@ void dev_set_promiscuity(struct net_device *dev, int inc)
2517 else 2507 else
2518 dev->flags |= IFF_PROMISC; 2508 dev->flags |= IFF_PROMISC;
2519 if (dev->flags != old_flags) { 2509 if (dev->flags != old_flags) {
2520 dev_mc_upload(dev);
2521 printk(KERN_INFO "device %s %s promiscuous mode\n", 2510 printk(KERN_INFO "device %s %s promiscuous mode\n",
2522 dev->name, (dev->flags & IFF_PROMISC) ? "entered" : 2511 dev->name, (dev->flags & IFF_PROMISC) ? "entered" :
2523 "left"); 2512 "left");
@@ -2531,6 +2520,25 @@ void dev_set_promiscuity(struct net_device *dev, int inc)
2531} 2520}
2532 2521
2533/** 2522/**
2523 * dev_set_promiscuity - update promiscuity count on a device
2524 * @dev: device
2525 * @inc: modifier
2526 *
2527 * Add or remove promiscuity from a device. While the count in the device
2528 * remains above zero the interface remains promiscuous. Once it hits zero
2529 * the device reverts back to normal filtering operation. A negative inc
2530 * value is used to drop promiscuity on the device.
2531 */
2532void dev_set_promiscuity(struct net_device *dev, int inc)
2533{
2534 unsigned short old_flags = dev->flags;
2535
2536 __dev_set_promiscuity(dev, inc);
2537 if (dev->flags != old_flags)
2538 dev_set_rx_mode(dev);
2539}
2540
2541/**
2534 * dev_set_allmulti - update allmulti count on a device 2542 * dev_set_allmulti - update allmulti count on a device
2535 * @dev: device 2543 * @dev: device
2536 * @inc: modifier 2544 * @inc: modifier
@@ -2550,7 +2558,48 @@ void dev_set_allmulti(struct net_device *dev, int inc)
2550 if ((dev->allmulti += inc) == 0) 2558 if ((dev->allmulti += inc) == 0)
2551 dev->flags &= ~IFF_ALLMULTI; 2559 dev->flags &= ~IFF_ALLMULTI;
2552 if (dev->flags ^ old_flags) 2560 if (dev->flags ^ old_flags)
2553 dev_mc_upload(dev); 2561 dev_set_rx_mode(dev);
2562}
2563
2564/*
2565 * Upload unicast and multicast address lists to device and
2566 * configure RX filtering. When the device doesn't support unicast
2567 * filtering it is put in promiscous mode while unicast addresses
2568 * are present.
2569 */
2570void __dev_set_rx_mode(struct net_device *dev)
2571{
2572 /* dev_open will call this function so the list will stay sane. */
2573 if (!(dev->flags&IFF_UP))
2574 return;
2575
2576 if (!netif_device_present(dev))
2577 return;
2578
2579 if (dev->set_rx_mode)
2580 dev->set_rx_mode(dev);
2581 else {
2582 /* Unicast addresses changes may only happen under the rtnl,
2583 * therefore calling __dev_set_promiscuity here is safe.
2584 */
2585 if (dev->uc_count > 0 && !dev->uc_promisc) {
2586 __dev_set_promiscuity(dev, 1);
2587 dev->uc_promisc = 1;
2588 } else if (dev->uc_count == 0 && dev->uc_promisc) {
2589 __dev_set_promiscuity(dev, -1);
2590 dev->uc_promisc = 0;
2591 }
2592
2593 if (dev->set_multicast_list)
2594 dev->set_multicast_list(dev);
2595 }
2596}
2597
2598void dev_set_rx_mode(struct net_device *dev)
2599{
2600 netif_tx_lock_bh(dev);
2601 __dev_set_rx_mode(dev);
2602 netif_tx_unlock_bh(dev);
2554} 2603}
2555 2604
2556int __dev_addr_delete(struct dev_addr_list **list, void *addr, int alen, 2605int __dev_addr_delete(struct dev_addr_list **list, void *addr, int alen,
@@ -2622,6 +2671,66 @@ void __dev_addr_discard(struct dev_addr_list **list)
2622 } 2671 }
2623} 2672}
2624 2673
2674/**
2675 * dev_unicast_delete - Release secondary unicast address.
2676 * @dev: device
2677 *
2678 * Release reference to a secondary unicast address and remove it
2679 * from the device if the reference count drop to zero.
2680 *
2681 * The caller must hold the rtnl_mutex.
2682 */
2683int dev_unicast_delete(struct net_device *dev, void *addr, int alen)
2684{
2685 int err;
2686
2687 ASSERT_RTNL();
2688
2689 netif_tx_lock_bh(dev);
2690 err = __dev_addr_delete(&dev->uc_list, addr, alen, 0);
2691 if (!err) {
2692 dev->uc_count--;
2693 __dev_set_rx_mode(dev);
2694 }
2695 netif_tx_unlock_bh(dev);
2696 return err;
2697}
2698EXPORT_SYMBOL(dev_unicast_delete);
2699
2700/**
2701 * dev_unicast_add - add a secondary unicast address
2702 * @dev: device
2703 *
2704 * Add a secondary unicast address to the device or increase
2705 * the reference count if it already exists.
2706 *
2707 * The caller must hold the rtnl_mutex.
2708 */
2709int dev_unicast_add(struct net_device *dev, void *addr, int alen)
2710{
2711 int err;
2712
2713 ASSERT_RTNL();
2714
2715 netif_tx_lock_bh(dev);
2716 err = __dev_addr_add(&dev->uc_list, addr, alen, 0);
2717 if (!err) {
2718 dev->uc_count++;
2719 __dev_set_rx_mode(dev);
2720 }
2721 netif_tx_unlock_bh(dev);
2722 return err;
2723}
2724EXPORT_SYMBOL(dev_unicast_add);
2725
2726static void dev_unicast_discard(struct net_device *dev)
2727{
2728 netif_tx_lock_bh(dev);
2729 __dev_addr_discard(&dev->uc_list);
2730 dev->uc_count = 0;
2731 netif_tx_unlock_bh(dev);
2732}
2733
2625unsigned dev_get_flags(const struct net_device *dev) 2734unsigned dev_get_flags(const struct net_device *dev)
2626{ 2735{
2627 unsigned flags; 2736 unsigned flags;
@@ -2665,7 +2774,7 @@ int dev_change_flags(struct net_device *dev, unsigned flags)
2665 * Load in the correct multicast list now the flags have changed. 2774 * Load in the correct multicast list now the flags have changed.
2666 */ 2775 */
2667 2776
2668 dev_mc_upload(dev); 2777 dev_set_rx_mode(dev);
2669 2778
2670 /* 2779 /*
2671 * Have we downed the interface. We handle IFF_UP ourselves 2780 * Have we downed the interface. We handle IFF_UP ourselves
@@ -2678,7 +2787,7 @@ int dev_change_flags(struct net_device *dev, unsigned flags)
2678 ret = ((old_flags & IFF_UP) ? dev_close : dev_open)(dev); 2787 ret = ((old_flags & IFF_UP) ? dev_close : dev_open)(dev);
2679 2788
2680 if (!ret) 2789 if (!ret)
2681 dev_mc_upload(dev); 2790 dev_set_rx_mode(dev);
2682 } 2791 }
2683 2792
2684 if (dev->flags & IFF_UP && 2793 if (dev->flags & IFF_UP &&
@@ -3558,8 +3667,9 @@ void unregister_netdevice(struct net_device *dev)
3558 raw_notifier_call_chain(&netdev_chain, NETDEV_UNREGISTER, dev); 3667 raw_notifier_call_chain(&netdev_chain, NETDEV_UNREGISTER, dev);
3559 3668
3560 /* 3669 /*
3561 * Flush the multicast chain 3670 * Flush the unicast and multicast chains
3562 */ 3671 */
3672 dev_unicast_discard(dev);
3563 dev_mc_discard(dev); 3673 dev_mc_discard(dev);
3564 3674
3565 if (dev->uninit) 3675 if (dev->uninit)
diff --git a/net/core/dev_mcast.c b/net/core/dev_mcast.c
index 702907434a47..5cc9b448c443 100644
--- a/net/core/dev_mcast.c
+++ b/net/core/dev_mcast.c
@@ -64,39 +64,6 @@
64 */ 64 */
65 65
66/* 66/*
67 * Update the multicast list into the physical NIC controller.
68 */
69
70static void __dev_mc_upload(struct net_device *dev)
71{
72 /* Don't do anything till we up the interface
73 * [dev_open will call this function so the list will
74 * stay sane]
75 */
76
77 if (!(dev->flags&IFF_UP))
78 return;
79
80 /*
81 * Devices with no set multicast or which have been
82 * detached don't get set.
83 */
84
85 if (dev->set_multicast_list == NULL ||
86 !netif_device_present(dev))
87 return;
88
89 dev->set_multicast_list(dev);
90}
91
92void dev_mc_upload(struct net_device *dev)
93{
94 netif_tx_lock_bh(dev);
95 __dev_mc_upload(dev);
96 netif_tx_unlock_bh(dev);
97}
98
99/*
100 * Delete a device level multicast 67 * Delete a device level multicast
101 */ 68 */
102 69
@@ -114,7 +81,7 @@ int dev_mc_delete(struct net_device *dev, void *addr, int alen, int glbl)
114 * loaded filter is now wrong. Fix it 81 * loaded filter is now wrong. Fix it
115 */ 82 */
116 83
117 __dev_mc_upload(dev); 84 __dev_set_rx_mode(dev);
118 } 85 }
119 netif_tx_unlock_bh(dev); 86 netif_tx_unlock_bh(dev);
120 return err; 87 return err;
@@ -132,7 +99,7 @@ int dev_mc_add(struct net_device *dev, void *addr, int alen, int glbl)
132 err = __dev_addr_add(&dev->mc_list, addr, alen, glbl); 99 err = __dev_addr_add(&dev->mc_list, addr, alen, glbl);
133 if (!err) { 100 if (!err) {
134 dev->mc_count++; 101 dev->mc_count++;
135 __dev_mc_upload(dev); 102 __dev_set_rx_mode(dev);
136 } 103 }
137 netif_tx_unlock_bh(dev); 104 netif_tx_unlock_bh(dev);
138 return err; 105 return err;