fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / net / 8021q / vlan_dev.c
index b91d251..425912a 100644 (file)
@@ -1,4 +1,4 @@
-/*
+/* -*- linux-c -*-
  * INET                802.1Q VLAN
  *             Ethernet-type device handling.
  *
@@ -62,7 +62,7 @@ int vlan_dev_rebuild_header(struct sk_buff *skb)
        default:
                printk(VLAN_DBG
                       "%s: unable to resolve type %X addresses.\n", 
-                      dev->name, (int)veth->h_vlan_encapsulated_proto);
+                      dev->name, ntohs(veth->h_vlan_encapsulated_proto));
         
                memcpy(veth->h_source, dev->dev_addr, ETH_ALEN);
                break;
@@ -113,14 +113,14 @@ static inline struct sk_buff *vlan_check_reorder_header(struct sk_buff *skb)
  *
  */
 int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
-                  struct packet_type* ptype)
+                  struct packet_type* ptype, struct net_device *orig_dev)
 {
        unsigned char *rawp = NULL;
        struct vlan_hdr *vhdr = (struct vlan_hdr *)(skb->data);
        unsigned short vid;
        struct net_device_stats *stats;
        unsigned short vlan_TCI;
-       unsigned short proto;
+       __be16 proto;
 
        /* vlan_TCI = ntohs(get_unaligned(&vhdr->h_vlan_TCI)); */
        vlan_TCI = ntohs(vhdr->h_vlan_TCI);
@@ -138,15 +138,15 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
 
        /* We have 12 bits of vlan ID.
         *
-        * We must not drop the vlan_group_lock until we hold a
+        * We must not drop allow preempt until we hold a
         * reference to the device (netif_rx does that) or we
         * fail.
         */
 
-       spin_lock_bh(&vlan_group_lock);
+       rcu_read_lock();
        skb->dev = __find_vlan_dev(dev, vid);
        if (!skb->dev) {
-               spin_unlock_bh(&vlan_group_lock);
+               rcu_read_unlock();
 
 #ifdef VLAN_DEBUG
                printk(VLAN_DBG "%s: ERROR: No net_device for VID: %i on dev: %s [%i]\n",
@@ -163,14 +163,15 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
        stats->rx_packets++;
        stats->rx_bytes += skb->len;
 
-       skb_pull(skb, VLAN_HLEN); /* take off the VLAN header (4 bytes currently) */
+       /* Take off the VLAN header (4 bytes currently) */
+       skb_pull_rcsum(skb, VLAN_HLEN);
 
        /* Ok, lets check to make sure the device (dev) we
         * came in on is what this VLAN is attached to.
         */
 
        if (dev != VLAN_DEV_INFO(skb->dev)->real_dev) {
-               spin_unlock_bh(&vlan_group_lock);
+               rcu_read_unlock();
 
 #ifdef VLAN_DEBUG
                printk(VLAN_DBG "%s: dropping skb: %p because came in on wrong device, dev: %s  real_dev: %s, skb_dev: %s\n",
@@ -211,7 +212,7 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
                 * This allows the VLAN to have a different MAC than the underlying
                 * device, and still route correctly.
                 */
-               if (memcmp(skb->mac.ethernet->h_dest, skb->dev->dev_addr, ETH_ALEN) == 0) {
+               if (!compare_ether_addr(eth_hdr(skb)->h_dest, skb->dev->dev_addr)) {
                        /* It is for our (changed) MAC-address! */
                        skb->pkt_type = PACKET_HOST;
                }
@@ -244,7 +245,7 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
                        /* TODO:  Add a more specific counter here. */
                        stats->rx_errors++;
                }
-               spin_unlock_bh(&vlan_group_lock);
+               rcu_read_unlock();
                return 0;
        }
 
@@ -273,7 +274,7 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
                        /* TODO:  Add a more specific counter here. */
                        stats->rx_errors++;
                }
-               spin_unlock_bh(&vlan_group_lock);
+               rcu_read_unlock();
                return 0;
        }
 
@@ -296,7 +297,7 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
                /* TODO:  Add a more specific counter here. */
                stats->rx_errors++;
        }
-       spin_unlock_bh(&vlan_group_lock);
+       rcu_read_unlock();
        return 0;
 }
 
@@ -379,6 +380,9 @@ int vlan_dev_hard_header(struct sk_buff *skb, struct net_device *dev,
                } else {
                        vhdr->h_vlan_encapsulated_proto = htons(len);
                }
+
+               skb->protocol = htons(ETH_P_8021Q);
+               skb->nh.raw = skb->data;
        }
 
        /* Before delegating work to the lower layer, enter our MAC-address */
@@ -527,7 +531,7 @@ int vlan_dev_change_mtu(struct net_device *dev, int new_mtu)
 
        dev->mtu = new_mtu;
 
-       return new_mtu;
+       return 0;
 }
 
 int vlan_dev_set_ingress_priority(char *dev_name, __u32 skb_prio, short vlan_prio)
@@ -622,6 +626,44 @@ int vlan_dev_set_vlan_flag(char *dev_name, __u32 flag, short flag_val)
        return -EINVAL;
 }
 
+
+int vlan_dev_get_realdev_name(const char *dev_name, char* result)
+{
+       struct net_device *dev = dev_get_by_name(dev_name);
+       int rv = 0;
+       if (dev) {
+               if (dev->priv_flags & IFF_802_1Q_VLAN) {
+                       strncpy(result, VLAN_DEV_INFO(dev)->real_dev->name, 23);
+                       rv = 0;
+               } else {
+                       rv = -EINVAL;
+               }
+               dev_put(dev);
+       } else {
+               rv = -ENODEV;
+       }
+       return rv;
+}
+
+int vlan_dev_get_vid(const char *dev_name, unsigned short* result)
+{
+       struct net_device *dev = dev_get_by_name(dev_name);
+       int rv = 0;
+       if (dev) {
+               if (dev->priv_flags & IFF_802_1Q_VLAN) {
+                       *result = VLAN_DEV_INFO(dev)->vlan_id;
+                       rv = 0;
+               } else {
+                       rv = -EINVAL;
+               }
+               dev_put(dev);
+       } else {
+               rv = -ENODEV;
+       }
+       return rv;
+}
+
+
 int vlan_dev_set_mac_address(struct net_device *dev, void *addr_struct_p)
 {
        struct sockaddr *addr = (struct sockaddr *)(addr_struct_p);
@@ -727,7 +769,6 @@ static void vlan_flush_mc_list(struct net_device *dev)
        struct dev_mc_list *dmi = dev->mc_list;
 
        while (dmi) {
-               dev_mc_delete(dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
                printk(KERN_DEBUG "%s: del %.2x:%.2x:%.2x:%.2x:%.2x:%.2x mcast address from vlan interface\n",
                       dev->name,
                       dmi->dmi_addr[0],
@@ -736,6 +777,7 @@ static void vlan_flush_mc_list(struct net_device *dev)
                       dmi->dmi_addr[3],
                       dmi->dmi_addr[4],
                       dmi->dmi_addr[5]);
+               dev_mc_delete(dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
                dmi = dev->mc_list;
        }
 
@@ -757,6 +799,34 @@ int vlan_dev_stop(struct net_device *dev)
        vlan_flush_mc_list(dev);
        return 0;
 }
+
+int vlan_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+       struct net_device *real_dev = VLAN_DEV_INFO(dev)->real_dev;
+       struct ifreq ifrr;
+       int err = -EOPNOTSUPP;
+
+       strncpy(ifrr.ifr_name, real_dev->name, IFNAMSIZ);
+       ifrr.ifr_ifru = ifr->ifr_ifru;
+
+       switch(cmd) {
+       case SIOCGMIIPHY:
+       case SIOCGMIIREG:
+       case SIOCSMIIREG:
+               if (real_dev->do_ioctl && netif_device_present(real_dev)) 
+                       err = real_dev->do_ioctl(real_dev, &ifrr, cmd);
+               break;
+
+       case SIOCETHTOOL:
+               err = dev_ethtool(&ifrr);
+       }
+
+       if (!err) 
+               ifr->ifr_ifru = ifrr.ifr_ifru;
+
+       return err;
+}
+
 /** Taken from Gleb + Lennert's VLAN code, and modified... */
 void vlan_dev_set_multicast_list(struct net_device *vlan_dev)
 {