Set skb->dev before calling netif_rx().
[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->dev = netdev;
31         skb->pkt_type = PACKET_HOST;
32         skb->protocol = eth_type_trans(skb, netdev);
33         if (in_interrupt())
34                 netif_rx(skb);
35         else
36                 netif_rx_ni(skb);
37         netdev->last_rx = jiffies;
38         dp_dev->stats.rx_packets++;
39         dp_dev->stats.rx_bytes += len;
40         return len;
41 }
42
43 static int dp_dev_mac_addr(struct net_device *dev, void *p)
44 {
45         struct sockaddr *addr = p;
46
47         if (netif_running(dev))
48                 return -EBUSY;
49         if (!is_valid_ether_addr(addr->sa_data))
50                 return -EADDRNOTAVAIL;
51         memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
52         return 0;
53 }
54
55 static int dp_dev_xmit(struct sk_buff *skb, struct net_device *netdev)
56 {
57         struct dp_dev *dp_dev = dp_dev_priv(netdev);
58         struct datapath *dp;
59         rcu_read_lock();
60         dp = dp_dev->dp;
61         if (likely(dp != NULL)) {
62                 dp_dev->stats.tx_packets++;
63                 dp_dev->stats.tx_bytes += skb->len;
64                 skb_reset_mac_header(skb);
65                 fwd_port_input(dp->chain, skb, OFPP_LOCAL);
66         } else {
67                 dp_dev->stats.tx_dropped++;
68                 kfree_skb(skb);
69         }
70         rcu_read_unlock();
71         return 0;
72 }
73
74 static int dp_dev_open(struct net_device *netdev)
75 {
76         netif_start_queue(netdev);
77         return 0;
78 }
79
80 static int dp_dev_stop(struct net_device *netdev)
81 {
82         netif_stop_queue(netdev);
83         return 0;
84 }
85
86 static void
87 do_setup(struct net_device *netdev)
88 {
89         ether_setup(netdev);
90
91         netdev->get_stats = dp_dev_get_stats;
92         netdev->hard_start_xmit = dp_dev_xmit;
93         netdev->open = dp_dev_open;
94         netdev->stop = dp_dev_stop;
95         netdev->tx_queue_len = 0;
96         netdev->set_mac_address = dp_dev_mac_addr;
97
98         netdev->flags = IFF_BROADCAST | IFF_MULTICAST;
99
100         random_ether_addr(netdev->dev_addr);
101 }
102
103
104 int dp_dev_setup(struct datapath *dp)
105 {
106         struct dp_dev *dp_dev;
107         struct net_device *netdev;
108         char of_name[8];
109         int err;
110
111         snprintf(of_name, sizeof of_name, "of%d", dp->dp_idx);
112         netdev = alloc_netdev(sizeof(struct dp_dev), of_name, do_setup);
113         if (!netdev)
114                 return -ENOMEM;
115
116         err = register_netdev(netdev);
117         if (err) {
118                 free_netdev(netdev);
119                 return err;
120         }
121
122         dp_dev = dp_dev_priv(netdev);
123         dp_dev->dp = dp;
124         dp->netdev = netdev;
125         return 0;
126 }
127
128 void dp_dev_destroy(struct datapath *dp)
129 {
130         struct dp_dev *dp_dev = dp_dev_priv(dp->netdev);
131         dp_dev->dp = NULL;
132         synchronize_net();
133         unregister_netdev(dp->netdev);
134         free_netdev(dp->netdev);
135 }
136
137 int is_dp_dev(struct net_device *netdev) 
138 {
139         return netdev->open == dp_dev_open;
140 }