2 * Inter process networking (virtual distributed ethernet) module
3 * Net devices: tap and grab
4 * (part of the View-OS project: wiki.virtualsquare.org)
6 * Copyright (C) 2007 Renzo Davoli (renzo@cs.unibo.it)
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * Due to this file being licensed under the GPL there is controversy over
14 * whether this permits you to write a module that #includes this file
15 * without placing your module under the GPL. Please consult a lawyer for
16 * advice before doing this.
18 * WARNING: THIS CODE IS ALREADY EXPERIMENTAL
22 #include <linux/init.h>
23 #include <linux/module.h>
24 #include <linux/socket.h>
25 #include <linux/poll.h>
27 #include <linux/list.h>
28 #include <linux/mount.h>
29 #include <linux/etherdevice.h>
30 #include <linux/ethtool.h>
31 #include <linux/version.h>
34 #include "ipn_netdev.h"
36 #define DRV_NAME "ipn"
37 #define DRV_VERSION "0.3"
39 static const struct ethtool_ops ipn_ethtool_ops
;
42 struct ipn_node
*ipn_node
;
43 struct net_device_stats stats
;
46 /* TAP Net device open. */
47 static int ipntap_net_open(struct net_device
*dev
)
49 netif_start_queue(dev
);
53 /* TAP Net device close. */
54 static int ipntap_net_close(struct net_device
*dev
)
56 netif_stop_queue(dev
);
60 static struct net_device_stats
*ipntap_net_stats(struct net_device
*dev
)
62 struct ipntap
*ipntap
= netdev_priv(dev
);
63 return &ipntap
->stats
;
66 /* receive from a TAP */
67 static int ipn_net_xmit(struct sk_buff
*skb
, struct net_device
*dev
)
69 struct ipntap
*ipntap
= netdev_priv(dev
);
70 struct ipn_node
*ipn_node
=ipntap
->ipn_node
;
71 struct msgpool_item
*newmsg
;
72 if (!ipn_node
|| !ipn_node
->ipn
|| skb
->len
> ipn_node
->ipn
->mtu
)
74 newmsg
=ipn_msgpool_alloc(ipn_node
->ipn
,1);
78 memcpy(newmsg
->data
,skb
->data
,skb
->len
);
79 ipn_proto_injectmsg(ipntap
->ipn_node
,newmsg
);
80 ipn_msgpool_put(newmsg
,ipn_node
->ipn
);
81 ipntap
->stats
.tx_packets
++;
82 ipntap
->stats
.tx_bytes
+= skb
->len
;
87 ipntap
->stats
.tx_dropped
++;
92 /* receive from a GRAB via interface hook */
93 struct sk_buff
*ipn_handle_hook(struct ipn_node
*ipn_node
, struct sk_buff
*skb
)
95 char *data
=(skb
->data
)-(skb
->mac_len
);
96 int len
=skb
->len
+skb
->mac_len
;
99 ((ipn_node
->flags
& IPN_NODEFLAG_DEVMASK
) == IPN_NODEFLAG_GRAB
) &&
100 ipn_node
->ipn
&& len
<=ipn_node
->ipn
->mtu
) {
101 struct msgpool_item
*newmsg
;
102 newmsg
=ipn_msgpool_alloc(ipn_node
->ipn
,1);
105 memcpy(newmsg
->data
,data
,len
);
106 ipn_proto_injectmsg(ipn_node
,newmsg
);
107 ipn_msgpool_put(newmsg
,ipn_node
->ipn
);
114 static void ipntap_setup(struct net_device
*dev
)
116 dev
->open
= ipntap_net_open
;
117 dev
->hard_start_xmit
= ipn_net_xmit
;
118 dev
->stop
= ipntap_net_close
;
119 dev
->get_stats
= ipntap_net_stats
;
120 dev
->ethtool_ops
= &ipn_ethtool_ops
;
124 struct net_device
*ipn_netdev_alloc(struct net
*net
,int type
, char *name
, int *err
)
126 struct net_device
*dev
=NULL
;
128 if (!name
|| *name
==0)
131 case IPN_NODEFLAG_TAP
:
132 dev
=alloc_netdev(sizeof(struct ipntap
), name
, ipntap_setup
);
136 /* this commented code is similar to tuntap MAC assignment.
137 * why tuntap does not use the random_ether_addr?
138 *(u16 *)dev->dev_addr = htons(0x00FF);
139 get_random_bytes(dev->dev_addr + sizeof(u16), 4);*/
140 random_ether_addr((u8
*)&dev
->dev_addr
);
142 case IPN_NODEFLAG_GRAB
:
143 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
144 dev
=dev_get_by_name(name
);
146 dev
=dev_get_by_name(net
,name
);
149 if (dev
->flags
& IFF_LOOPBACK
)
151 else if (rcu_dereference(dev
->ipn_port
) != NULL
)
161 int ipn_netdev_activate(struct ipn_node
*ipn_node
)
164 switch (ipn_node
->flags
& IPN_NODEFLAG_DEVMASK
) {
165 case IPN_NODEFLAG_TAP
:
167 struct ipntap
*ipntap
=netdev_priv(ipn_node
->dev
);
168 ipntap
->ipn_node
=ipn_node
;
170 if ((rv
=register_netdevice(ipn_node
->dev
)) == 0)
171 rcu_assign_pointer(ipn_node
->dev
->ipn_port
,
177 if (rv
) {/* error! */
178 ipn_node
->flags
&= ~IPN_NODEFLAG_DEVMASK
;
179 free_netdev(ipn_node
->dev
);
183 case IPN_NODEFLAG_GRAB
:
185 rcu_assign_pointer(ipn_node
->dev
->ipn_port
,
190 dev_set_promiscuity(ipn_node
->dev
,1);
198 void ipn_netdev_close(struct ipn_node
*ipn_node
)
200 switch (ipn_node
->flags
& IPN_NODEFLAG_DEVMASK
) {
201 case IPN_NODEFLAG_TAP
:
202 ipn_node
->flags
&= ~IPN_NODEFLAG_DEVMASK
;
204 rcu_assign_pointer(ipn_node
->dev
->ipn_port
, NULL
);
205 unregister_netdevice(ipn_node
->dev
);
207 free_netdev(ipn_node
->dev
);
209 case IPN_NODEFLAG_GRAB
:
210 ipn_node
->flags
&= ~IPN_NODEFLAG_DEVMASK
;
212 rcu_assign_pointer(ipn_node
->dev
->ipn_port
, NULL
);
213 dev_set_promiscuity(ipn_node
->dev
,-1);
219 void ipn_netdev_sendmsg(struct ipn_node
*to
,struct msgpool_item
*msg
)
222 struct net_device
*dev
=to
->dev
;
223 struct ipntap
*ipntap
=netdev_priv(dev
);
225 if (msg
->len
> dev
->mtu
)
227 skb
=alloc_skb(msg
->len
+NET_IP_ALIGN
,GFP_KERNEL
);
229 ipntap
->stats
.rx_dropped
++;
232 memcpy(skb_put(skb
,msg
->len
),msg
->data
,msg
->len
);
233 switch (to
->flags
& IPN_NODEFLAG_DEVMASK
) {
234 case IPN_NODEFLAG_TAP
:
235 skb
->protocol
= eth_type_trans(skb
, dev
);
237 ipntap
->stats
.rx_packets
++;
238 ipntap
->stats
.rx_bytes
+= msg
->len
;
240 case IPN_NODEFLAG_GRAB
:
247 /* ethtool interface */
249 static int ipn_get_settings(struct net_device
*dev
, struct ethtool_cmd
*cmd
)
252 cmd
->advertising
= 0;
253 cmd
->speed
= SPEED_10
;
254 cmd
->duplex
= DUPLEX_FULL
;
256 cmd
->phy_address
= 0;
257 cmd
->transceiver
= XCVR_INTERNAL
;
258 cmd
->autoneg
= AUTONEG_DISABLE
;
264 static void ipn_get_drvinfo(struct net_device
*dev
, struct ethtool_drvinfo
*info
)
266 strcpy(info
->driver
, DRV_NAME
);
267 strcpy(info
->version
, DRV_VERSION
);
268 strcpy(info
->fw_version
, "N/A");
271 static const struct ethtool_ops ipn_ethtool_ops
= {
272 .get_settings
= ipn_get_settings
,
273 .get_drvinfo
= ipn_get_drvinfo
,
274 /* not implemented (yet?)
275 .get_msglevel = ipn_get_msglevel,
276 .set_msglevel = ipn_set_msglevel,
277 .get_link = ipn_get_link,
278 .get_rx_csum = ipn_get_rx_csum,
279 .set_rx_csum = ipn_set_rx_csum */
282 int ipn_netdev_init(void)
284 ipn_handle_frame_hook
=
293 void ipn_netdev_fini(void)
295 ipn_handle_frame_hook
=NULL
;