Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 58936
b: refs/heads/master
c: 4417da6
h: refs/heads/master
v: v3
  • Loading branch information
Patrick McHardy authored and David S. Miller committed Jul 11, 2007
1 parent 05b1cd2 commit b110e5d
Show file tree
Hide file tree
Showing 4 changed files with 140 additions and 55 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 3fba5a8b1e3df2384b90493538161e83cf15dd5f
refs/heads/master: 4417da668c0021903464f92db278ddae348e0299
12 changes: 10 additions & 2 deletions trunk/include/linux/netdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,9 @@ struct net_device
unsigned char addr_len; /* hardware address length */
unsigned short dev_id; /* for shared network cards */

struct dev_addr_list *uc_list; /* Secondary unicast mac addresses */
int uc_count; /* Number of installed ucasts */
int uc_promisc;
struct dev_addr_list *mc_list; /* Multicast mac addresses */
int mc_count; /* Number of installed mcasts */
int promiscuity;
Expand Down Expand Up @@ -502,6 +505,8 @@ struct net_device
void *saddr,
unsigned len);
int (*rebuild_header)(struct sk_buff *skb);
#define HAVE_SET_RX_MODE
void (*set_rx_mode)(struct net_device *dev);
#define HAVE_MULTICAST
void (*set_multicast_list)(struct net_device *dev);
#define HAVE_SET_MAC_ADDR
Expand Down Expand Up @@ -1008,8 +1013,11 @@ extern struct net_device *alloc_netdev(int sizeof_priv, const char *name,
void (*setup)(struct net_device *));
extern int register_netdev(struct net_device *dev);
extern void unregister_netdev(struct net_device *dev);
/* Functions used for multicast support */
extern void dev_mc_upload(struct net_device *dev);
/* Functions used for secondary unicast and multicast support */
extern void dev_set_rx_mode(struct net_device *dev);
extern void __dev_set_rx_mode(struct net_device *dev);
extern int dev_unicast_delete(struct net_device *dev, void *addr, int alen);
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 void dev_mc_discard(struct net_device *dev);
Expand Down
144 changes: 127 additions & 17 deletions trunk/net/core/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -942,7 +942,7 @@ int dev_open(struct net_device *dev)
/*
* Initialize multicasting status
*/
dev_mc_upload(dev);
dev_set_rx_mode(dev);

/*
* Wakeup transmit queue engine
Expand Down Expand Up @@ -2498,17 +2498,7 @@ int netdev_set_master(struct net_device *slave, struct net_device *master)
return 0;
}

/**
* dev_set_promiscuity - update promiscuity count on a device
* @dev: device
* @inc: modifier
*
* Add or remove promiscuity from a device. While the count in the device
* remains above zero the interface remains promiscuous. Once it hits zero
* the device reverts back to normal filtering operation. A negative inc
* value is used to drop promiscuity on the device.
*/
void dev_set_promiscuity(struct net_device *dev, int inc)
static void __dev_set_promiscuity(struct net_device *dev, int inc)
{
unsigned short old_flags = dev->flags;

Expand All @@ -2517,7 +2507,6 @@ void dev_set_promiscuity(struct net_device *dev, int inc)
else
dev->flags |= IFF_PROMISC;
if (dev->flags != old_flags) {
dev_mc_upload(dev);
printk(KERN_INFO "device %s %s promiscuous mode\n",
dev->name, (dev->flags & IFF_PROMISC) ? "entered" :
"left");
Expand All @@ -2530,6 +2519,25 @@ void dev_set_promiscuity(struct net_device *dev, int inc)
}
}

/**
* dev_set_promiscuity - update promiscuity count on a device
* @dev: device
* @inc: modifier
*
* Add or remove promiscuity from a device. While the count in the device
* remains above zero the interface remains promiscuous. Once it hits zero
* the device reverts back to normal filtering operation. A negative inc
* value is used to drop promiscuity on the device.
*/
void dev_set_promiscuity(struct net_device *dev, int inc)
{
unsigned short old_flags = dev->flags;

__dev_set_promiscuity(dev, inc);
if (dev->flags != old_flags)
dev_set_rx_mode(dev);
}

/**
* dev_set_allmulti - update allmulti count on a device
* @dev: device
Expand All @@ -2550,7 +2558,48 @@ void dev_set_allmulti(struct net_device *dev, int inc)
if ((dev->allmulti += inc) == 0)
dev->flags &= ~IFF_ALLMULTI;
if (dev->flags ^ old_flags)
dev_mc_upload(dev);
dev_set_rx_mode(dev);
}

/*
* Upload unicast and multicast address lists to device and
* configure RX filtering. When the device doesn't support unicast
* filtering it is put in promiscous mode while unicast addresses
* are present.
*/
void __dev_set_rx_mode(struct net_device *dev)
{
/* dev_open will call this function so the list will stay sane. */
if (!(dev->flags&IFF_UP))
return;

if (!netif_device_present(dev))
return;

if (dev->set_rx_mode)
dev->set_rx_mode(dev);
else {
/* Unicast addresses changes may only happen under the rtnl,
* therefore calling __dev_set_promiscuity here is safe.
*/
if (dev->uc_count > 0 && !dev->uc_promisc) {
__dev_set_promiscuity(dev, 1);
dev->uc_promisc = 1;
} else if (dev->uc_count == 0 && dev->uc_promisc) {
__dev_set_promiscuity(dev, -1);
dev->uc_promisc = 0;
}

if (dev->set_multicast_list)
dev->set_multicast_list(dev);
}
}

void dev_set_rx_mode(struct net_device *dev)
{
netif_tx_lock_bh(dev);
__dev_set_rx_mode(dev);
netif_tx_unlock_bh(dev);
}

int __dev_addr_delete(struct dev_addr_list **list, void *addr, int alen,
Expand Down Expand Up @@ -2622,6 +2671,66 @@ void __dev_addr_discard(struct dev_addr_list **list)
}
}

/**
* dev_unicast_delete - Release secondary unicast address.
* @dev: device
*
* Release reference to a secondary unicast address and remove it
* from the device if the reference count drop to zero.
*
* The caller must hold the rtnl_mutex.
*/
int dev_unicast_delete(struct net_device *dev, void *addr, int alen)
{
int err;

ASSERT_RTNL();

netif_tx_lock_bh(dev);
err = __dev_addr_delete(&dev->uc_list, addr, alen, 0);
if (!err) {
dev->uc_count--;
__dev_set_rx_mode(dev);
}
netif_tx_unlock_bh(dev);
return err;
}
EXPORT_SYMBOL(dev_unicast_delete);

/**
* dev_unicast_add - add a secondary unicast address
* @dev: device
*
* Add a secondary unicast address to the device or increase
* the reference count if it already exists.
*
* The caller must hold the rtnl_mutex.
*/
int dev_unicast_add(struct net_device *dev, void *addr, int alen)
{
int err;

ASSERT_RTNL();

netif_tx_lock_bh(dev);
err = __dev_addr_add(&dev->uc_list, addr, alen, 0);
if (!err) {
dev->uc_count++;
__dev_set_rx_mode(dev);
}
netif_tx_unlock_bh(dev);
return err;
}
EXPORT_SYMBOL(dev_unicast_add);

static void dev_unicast_discard(struct net_device *dev)
{
netif_tx_lock_bh(dev);
__dev_addr_discard(&dev->uc_list);
dev->uc_count = 0;
netif_tx_unlock_bh(dev);
}

unsigned dev_get_flags(const struct net_device *dev)
{
unsigned flags;
Expand Down Expand Up @@ -2665,7 +2774,7 @@ int dev_change_flags(struct net_device *dev, unsigned flags)
* Load in the correct multicast list now the flags have changed.
*/

dev_mc_upload(dev);
dev_set_rx_mode(dev);

/*
* Have we downed the interface. We handle IFF_UP ourselves
Expand All @@ -2678,7 +2787,7 @@ int dev_change_flags(struct net_device *dev, unsigned flags)
ret = ((old_flags & IFF_UP) ? dev_close : dev_open)(dev);

if (!ret)
dev_mc_upload(dev);
dev_set_rx_mode(dev);
}

if (dev->flags & IFF_UP &&
Expand Down Expand Up @@ -3558,8 +3667,9 @@ void unregister_netdevice(struct net_device *dev)
raw_notifier_call_chain(&netdev_chain, NETDEV_UNREGISTER, dev);

/*
* Flush the multicast chain
* Flush the unicast and multicast chains
*/
dev_unicast_discard(dev);
dev_mc_discard(dev);

if (dev->uninit)
Expand Down
37 changes: 2 additions & 35 deletions trunk/net/core/dev_mcast.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,39 +63,6 @@
* We block accesses to device mc filters with netif_tx_lock.
*/

/*
* Update the multicast list into the physical NIC controller.
*/

static void __dev_mc_upload(struct net_device *dev)
{
/* Don't do anything till we up the interface
* [dev_open will call this function so the list will
* stay sane]
*/

if (!(dev->flags&IFF_UP))
return;

/*
* Devices with no set multicast or which have been
* detached don't get set.
*/

if (dev->set_multicast_list == NULL ||
!netif_device_present(dev))
return;

dev->set_multicast_list(dev);
}

void dev_mc_upload(struct net_device *dev)
{
netif_tx_lock_bh(dev);
__dev_mc_upload(dev);
netif_tx_unlock_bh(dev);
}

/*
* Delete a device level multicast
*/
Expand All @@ -114,7 +81,7 @@ int dev_mc_delete(struct net_device *dev, void *addr, int alen, int glbl)
* loaded filter is now wrong. Fix it
*/

__dev_mc_upload(dev);
__dev_set_rx_mode(dev);
}
netif_tx_unlock_bh(dev);
return err;
Expand All @@ -132,7 +99,7 @@ int dev_mc_add(struct net_device *dev, void *addr, int alen, int glbl)
err = __dev_addr_add(&dev->mc_list, addr, alen, glbl);
if (!err) {
dev->mc_count++;
__dev_mc_upload(dev);
__dev_set_rx_mode(dev);
}
netif_tx_unlock_bh(dev);
return err;
Expand Down

0 comments on commit b110e5d

Please sign in to comment.