Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 59057
b: refs/heads/master
c: 8c979c2
h: refs/heads/master
i:
  59055: 61d6e82
v: v3
  • Loading branch information
Patrick McHardy authored and David S. Miller committed Jul 12, 2007
1 parent 83333c7 commit 9770525
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 46 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: 71bffe556c59a7865bf0b1ecd94530f1e296cdb0
refs/heads/master: 8c979c26a0f093c13290320edda799d8335e50ae
1 change: 1 addition & 0 deletions trunk/include/linux/if_vlan.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ struct vlan_dev_info {
int old_allmulti; /* similar to above. */
int old_promiscuity; /* similar to above. */
struct net_device *real_dev; /* the underlying device/interface */
unsigned char real_dev_addr[ETH_ALEN];
struct proc_dir_entry *dent; /* Holds the proc data */
unsigned long cnt_inc_headroom_on_tx; /* How many times did we have to grow the skb on TX. */
unsigned long cnt_encap_on_xmit; /* How many times did we have to encapsulate the skb on TX. */
Expand Down
43 changes: 38 additions & 5 deletions trunk/net/8021q/vlan.c
Original file line number Diff line number Diff line change
Expand Up @@ -345,12 +345,8 @@ static int vlan_dev_init(struct net_device *dev)
(1<<__LINK_STATE_DORMANT))) |
(1<<__LINK_STATE_PRESENT);

/* TODO: maybe just assign it to be ETHERNET? */
dev->type = real_dev->type;

memcpy(dev->broadcast, real_dev->broadcast, real_dev->addr_len);
memcpy(dev->dev_addr, real_dev->dev_addr, real_dev->addr_len);
dev->addr_len = real_dev->addr_len;

if (real_dev->features & NETIF_F_HW_VLAN_TX) {
dev->hard_header = real_dev->hard_header;
Expand All @@ -364,6 +360,7 @@ static int vlan_dev_init(struct net_device *dev)
dev->rebuild_header = vlan_dev_rebuild_header;
}
dev->hard_header_parse = real_dev->hard_header_parse;
dev->hard_header_cache = NULL;

lockdep_set_class(&dev->_xmit_lock, &vlan_netdev_xmit_lock_key);
return 0;
Expand All @@ -373,6 +370,8 @@ void vlan_setup(struct net_device *new_dev)
{
SET_MODULE_OWNER(new_dev);

ether_setup(new_dev);

/* new_dev->ifindex = 0; it will be set when added to
* the global list.
* iflink is set as well.
Expand All @@ -392,7 +391,6 @@ void vlan_setup(struct net_device *new_dev)
new_dev->init = vlan_dev_init;
new_dev->open = vlan_dev_open;
new_dev->stop = vlan_dev_stop;
new_dev->set_mac_address = vlan_dev_set_mac_address;
new_dev->set_multicast_list = vlan_dev_set_multicast_list;
new_dev->destructor = free_netdev;
new_dev->do_ioctl = vlan_dev_ioctl;
Expand Down Expand Up @@ -592,6 +590,30 @@ static int register_vlan_device(struct net_device *real_dev,
return err;
}

static void vlan_sync_address(struct net_device *dev,
struct net_device *vlandev)
{
struct vlan_dev_info *vlan = VLAN_DEV_INFO(vlandev);

/* May be called without an actual change */
if (!compare_ether_addr(vlan->real_dev_addr, dev->dev_addr))
return;

/* vlan address was different from the old address and is equal to
* the new address */
if (compare_ether_addr(vlandev->dev_addr, vlan->real_dev_addr) &&
!compare_ether_addr(vlandev->dev_addr, dev->dev_addr))
dev_unicast_delete(dev, vlandev->dev_addr, ETH_ALEN);

/* vlan address was equal to the old address and is different from
* the new address */
if (!compare_ether_addr(vlandev->dev_addr, vlan->real_dev_addr) &&
compare_ether_addr(vlandev->dev_addr, dev->dev_addr))
dev_unicast_add(dev, vlandev->dev_addr, ETH_ALEN);

memcpy(vlan->real_dev_addr, dev->dev_addr, ETH_ALEN);
}

static int vlan_device_event(struct notifier_block *unused, unsigned long event, void *ptr)
{
struct net_device *dev = ptr;
Expand All @@ -618,6 +640,17 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
}
break;

case NETDEV_CHANGEADDR:
/* Adjust unicast filters on underlying device */
for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
vlandev = vlan_group_get_device(grp, i);
if (!vlandev)
continue;

vlan_sync_address(dev, vlandev);
}
break;

case NETDEV_DOWN:
/* Put all VLANs for this dev in the down state too. */
for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
Expand Down
1 change: 0 additions & 1 deletion trunk/net/8021q/vlan.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ int vlan_dev_hard_header(struct sk_buff *skb, struct net_device *dev,
int vlan_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev);
int vlan_dev_hwaccel_hard_start_xmit(struct sk_buff *skb, struct net_device *dev);
int vlan_dev_change_mtu(struct net_device *dev, int new_mtu);
int vlan_dev_set_mac_address(struct net_device *dev, void* addr);
int vlan_dev_open(struct net_device* dev);
int vlan_dev_stop(struct net_device* dev);
int vlan_dev_ioctl(struct net_device* dev, struct ifreq *ifr, int cmd);
Expand Down
57 changes: 18 additions & 39 deletions trunk/net/8021q/vlan_dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -612,44 +612,6 @@ void vlan_dev_get_vid(const struct net_device *dev, unsigned short *result)
*result = VLAN_DEV_INFO(dev)->vlan_id;
}

int vlan_dev_set_mac_address(struct net_device *dev, void *addr_struct_p)
{
struct sockaddr *addr = (struct sockaddr *)(addr_struct_p);
int i;

if (netif_running(dev))
return -EBUSY;

memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);

printk("%s: Setting MAC address to ", dev->name);
for (i = 0; i < 6; i++)
printk(" %2.2x", dev->dev_addr[i]);
printk(".\n");

if (memcmp(VLAN_DEV_INFO(dev)->real_dev->dev_addr,
dev->dev_addr,
dev->addr_len) != 0) {
if (!(VLAN_DEV_INFO(dev)->real_dev->flags & IFF_PROMISC)) {
int flgs = VLAN_DEV_INFO(dev)->real_dev->flags;

/* Increment our in-use promiscuity counter */
dev_set_promiscuity(VLAN_DEV_INFO(dev)->real_dev, 1);

/* Make PROMISC visible to the user. */
flgs |= IFF_PROMISC;
printk("VLAN (%s): Setting underlying device (%s) to promiscious mode.\n",
dev->name, VLAN_DEV_INFO(dev)->real_dev->name);
dev_change_flags(VLAN_DEV_INFO(dev)->real_dev, flgs);
}
} else {
printk("VLAN (%s): Underlying device (%s) has same MAC, not checking promiscious mode.\n",
dev->name, VLAN_DEV_INFO(dev)->real_dev->name);
}

return 0;
}

static inline int vlan_dmi_equals(struct dev_mc_list *dmi1,
struct dev_mc_list *dmi2)
{
Expand Down Expand Up @@ -736,15 +698,32 @@ static void vlan_flush_mc_list(struct net_device *dev)

int vlan_dev_open(struct net_device *dev)
{
if (!(VLAN_DEV_INFO(dev)->real_dev->flags & IFF_UP))
struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev);
struct net_device *real_dev = vlan->real_dev;
int err;

if (!(real_dev->flags & IFF_UP))
return -ENETDOWN;

if (compare_ether_addr(dev->dev_addr, real_dev->dev_addr)) {
err = dev_unicast_add(real_dev, dev->dev_addr, ETH_ALEN);
if (err < 0)
return err;
}
memcpy(vlan->real_dev_addr, real_dev->dev_addr, ETH_ALEN);

return 0;
}

int vlan_dev_stop(struct net_device *dev)
{
struct net_device *real_dev = VLAN_DEV_INFO(dev)->real_dev;

vlan_flush_mc_list(dev);

if (compare_ether_addr(dev->dev_addr, real_dev->dev_addr))
dev_unicast_delete(real_dev, dev->dev_addr, dev->addr_len);

return 0;
}

Expand Down

0 comments on commit 9770525

Please sign in to comment.