]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/ankh/server/netlib/linux_glue.c
Inital import
[l4.git] / l4 / pkg / ankh / server / netlib / linux_glue.c
1 #include <linux/netdevice.h>
2 #include <linux/init.h>
3 #include <linux/skbuff.h>
4 #include "linux_glue.h"
5
6 #include <l4/dde/linux26/dde26_net.h>
7 #undef __always_inline
8 #include <assert.h>
9
10 #define DEBUG(DBG, msg, ...) \
11         do { if (DBG) \
12                         printk(msg, ##__VA_ARGS__); \
13         } while (0);
14
15 #define ANKH_DEBUG_INIT     1
16 #define ANKH_DEBUG_PACKET   0
17
18 int ankh_debug_linuxglue = 0;
19 void ankh_set_debug()   { ++ankh_debug_linuxglue; }
20 void ankh_unset_debug() { --ankh_debug_linuxglue; }
21
22 /*****************************************************************************
23  * Open the "real" network devices. Return the number of opened interfaces.
24  *****************************************************************************/
25 int open_network_devices(int promisc)
26 {
27         struct net_device *dev;
28         struct net *net;
29         int err = 0, cnt = 0;
30
31         DEBUG(ANKH_DEBUG_INIT, "%s() \n", __func__);
32
33         for_each_net(net) {
34                 for_each_netdev(net, dev)
35                 {
36                         DEBUG(ANKH_DEBUG_INIT, "opening %s\n", dev->name);
37
38                         // beam us to promiscuous mode, so that we can receive packets that
39                         // are not meant for the NIC's MAC address --> we need that, because
40                         // ORe clients have different MAC addresses
41                         if (promisc && netdev_set_promisc(dev) == 0)
42                                         DEBUG(ANKH_DEBUG_INIT, "set interface to promiscuous mode.\n");
43
44                         err = dev_open(dev);
45                         if (err)
46                         {
47                                 DEBUG(ANKH_DEBUG_INIT, "error opening %s : %d\n", dev->name, err);
48                                 return err;
49                         }
50                         else // success
51                                 netdev_add(dev);
52
53                 cnt++;
54                 //xmit_lock_add(dev->name);
55                 }
56         }
57
58         return cnt;
59 }
60
61
62 static int net_recv_irq(struct sk_buff *skb)
63 {
64         int i;
65         
66         /*
67          * Special case: The loopback device is handled
68          * by local packet delivery beforehand. The loopback
69          * driver however, tries to directly call the recv() routine
70          * upon xmit(), too.
71          */
72         if (!strcmp(skb->dev->name, "lo"))
73                 return NET_RX_SUCCESS;
74
75         /*
76          * Push eth header back, so that skb->data is the raw packet.
77          */
78         skb_push(skb, skb->dev->hard_header_len);
79
80         /*
81          * Hand to upper layers.
82          */
83 #if 0
84         DECLARE_MAC_BUF(mac);
85         printk("%s\n", print_mac(mac, skb->data));
86 #endif
87         packet_deliver(skb->data, skb->len, skb->dev->name, 0);
88
89         /*
90          * Need to release skb here.
91          */
92         kfree_skb(skb);
93
94         return NET_RX_SUCCESS;
95 }
96
97
98 static void _init_linux_glue(void)
99 {
100         l4dde26_softirq_init();
101         skb_init();
102
103         l4dde26_register_rx_callback(net_recv_irq);
104 }
105 subsys_initcall(_init_linux_glue);
106
107 /*****************************************************************************
108  * wrapper functions for accessing net_device members
109  *****************************************************************************/
110
111 #define ND(p) ((struct net_device *)p)
112
113 int netdev_irq(void *netdev)
114 { return ND(netdev)->irq; }
115
116
117 char const *netdev_name(void *netdev)
118 { return dev_name(&ND(netdev)->dev); }
119
120
121 int netdev_set_promisc(void *netdev)
122 {
123         int err;
124         struct net_device *dev = ND(netdev);
125         if ((err = dev_change_flags(dev, dev->flags | IFF_PROMISC)) != 0)
126                 DEBUG(ANKH_DEBUG_INIT, "%s could not be set to promiscuous mode.\n",
127                                       dev->name);
128
129         return err;
130 }
131
132
133 int netdev_unset_promisc(void *netdev)
134 {
135         int err;
136         struct net_device *dev = ND(netdev);
137         if ((err = dev_change_flags(dev, dev->flags & ~IFF_PROMISC)) != 0)
138                 DEBUG(ANKH_DEBUG_INIT, "%s could not be set to promiscuous mode.\n",
139                                       dev->name);
140
141         return err;
142 }
143
144
145 void *alloc_dmaable_buffer(unsigned size)
146 {
147         return kmalloc(size, GFP_KERNEL);
148 }
149
150
151 int netdev_get_promisc(void *netdev)
152 { return ND(netdev)->flags & IFF_PROMISC; }
153
154
155 char *netdev_dev_addr(void *netdev)
156 { return ND(netdev)->dev_addr; }
157
158
159 int netdev_mtu(void *netdev)
160 { return ND(netdev)->mtu; }
161
162
163 int netdev_xmit(void *netdev, char *addr, unsigned len)
164 {
165         // XXX could we pass 0 as length here? data netdev is set
166         //     below anyway
167     struct sk_buff *skb = alloc_skb(len, GFP_KERNEL);
168     assert(skb);
169
170     skb->data = addr; // XXX
171     skb->len  = len;
172     skb->dev  = ND(netdev);
173
174     while (netif_queue_stopped(ND(netdev)))
175                 msleep(1);
176
177     int err;
178     if (ND(netdev)->netdev_ops)
179         err = ND(netdev)->netdev_ops->ndo_start_xmit(skb, ND(netdev));
180     else
181         err = ND(netdev)->hard_start_xmit(skb, ND(netdev));
182
183     return err;
184 }