Define skb_reset_mac_header for Linux 2.6 kernels older than 2.6.22.
[sliver-openvswitch.git] / datapath / dp_dev.c
1 #include <linux/kernel.h>
2 #include <linux/netdevice.h>
3 #include <linux/etherdevice.h>
4 #include <linux/rcupdate.h>
5 #include <linux/skbuff.h>
6
7 #include "datapath.h"
8 #include "forward.h"
9
10 struct dp_dev {
11         struct net_device_stats stats;
12         struct datapath *dp;
13 };
14
15 static struct dp_dev *dp_dev_priv(struct net_device *netdev) 
16 {
17         return netdev_priv(netdev);
18 }
19
20 static struct net_device_stats *dp_dev_get_stats(struct net_device *netdev)
21 {
22         struct dp_dev *dp_dev = dp_dev_priv(netdev);
23         return &dp_dev->stats;
24 }
25
26 int dp_dev_recv(struct net_device *netdev, struct sk_buff *skb) 
27 {
28         int len = skb->len;
29         struct dp_dev *dp_dev = dp_dev_priv(netdev);
30         skb->pkt_type = PACKET_HOST;
31         skb->protocol = eth_type_trans(skb, netdev);
32         netif_rx(skb);
33         netdev->last_rx = jiffies;
34         dp_dev->stats.rx_packets++;
35         dp_dev->stats.rx_bytes += len;
36         return len;
37 }
38
39 static int dp_dev_mac_addr(struct net_device *dev, void *p)
40 {
41         struct sockaddr *addr = p;
42
43         if (netif_running(dev))
44                 return -EBUSY;
45         if (!is_valid_ether_addr(addr->sa_data))
46                 return -EADDRNOTAVAIL;
47         memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
48         return 0;
49 }
50
51 static int dp_dev_xmit(struct sk_buff *skb, struct net_device *netdev)
52 {
53         struct dp_dev *dp_dev = dp_dev_priv(netdev);
54         struct datapath *dp;
55         rcu_read_lock();
56         dp = dp_dev->dp;
57         if (likely(dp != NULL)) {
58                 dp_dev->stats.tx_packets++;
59                 dp_dev->stats.tx_bytes += skb->len;
60                 skb_reset_mac_header(skb);
61                 fwd_port_input(dp->chain, skb, OFPP_LOCAL);
62         } else {
63                 dp_dev->stats.tx_dropped++;
64                 kfree_skb(skb);
65         }
66         rcu_read_unlock();
67         return 0;
68 }
69
70 static int dp_dev_open(struct net_device *netdev)
71 {
72         netif_start_queue(netdev);
73         return 0;
74 }
75
76 static int dp_dev_stop(struct net_device *netdev)
77 {
78         netif_stop_queue(netdev);
79         return 0;
80 }
81
82 static void
83 do_setup(struct net_device *netdev)
84 {
85         ether_setup(netdev);
86
87         netdev->get_stats = dp_dev_get_stats;
88         netdev->hard_start_xmit = dp_dev_xmit;
89         netdev->open = dp_dev_open;
90         netdev->stop = dp_dev_stop;
91         netdev->tx_queue_len = 0;
92         netdev->set_mac_address = dp_dev_mac_addr;
93
94         netdev->flags = IFF_BROADCAST | IFF_MULTICAST;
95
96         random_ether_addr(netdev->dev_addr);
97 }
98
99
100 int dp_dev_setup(struct datapath *dp)
101 {
102         struct dp_dev *dp_dev;
103         struct net_device *netdev;
104         char of_name[8];
105         int err;
106
107         snprintf(of_name, sizeof of_name, "of%d", dp->dp_idx);
108         netdev = alloc_netdev(sizeof(struct dp_dev), of_name, do_setup);
109         if (!netdev)
110                 return -ENOMEM;
111
112         err = register_netdev(netdev);
113         if (err) {
114                 free_netdev(netdev);
115                 return err;
116         }
117
118         dp_dev = dp_dev_priv(netdev);
119         dp_dev->dp = dp;
120         dp->netdev = netdev;
121         return 0;
122 }
123
124 void dp_dev_destroy(struct datapath *dp)
125 {
126         struct dp_dev *dp_dev = dp_dev_priv(dp->netdev);
127         dp_dev->dp = NULL;
128         synchronize_net();
129         unregister_netdev(dp->netdev);
130         free_netdev(dp->netdev);
131 }
132
133 int is_dp_dev(struct net_device *netdev) 
134 {
135         return netdev->open == dp_dev_open;
136 }