* Updated to release 1.1a "Try before release"
[vde.git] / ipn / kvde_switch / kvde_switch_main.c
blobca77001f6a3d68a4339c184900b0eb570c464997
1 #include <linux/module.h>
2 #include <linux/if_ether.h>
3 #include "../af_ipn.h"
4 #include "ipn_hash.h"
6 MODULE_LICENSE("GPL");
7 MODULE_AUTHOR("VIEW-OS TEAM");
8 MODULE_DESCRIPTION("VDE SWITCH Kernel Module");
10 static struct kmem_cache *kvde_net_cache;
11 #define IS_BROADCAST(addr) ((addr[0] & 1) == 1)
13 static int ipn_kvde_switch_newport(struct ipn_node *newport) {
14 struct ipn_network *ipnn=newport->ipn;
15 int i;
16 for (i=0;i<ipnn->maxports;i++) {
17 if (ipnn->connport[i] == NULL)
18 return i;
20 return -1;
23 static int ipn_kvde_switch_handlemsg(struct ipn_node *from,
24 struct msgpool_item *msgitem){
25 struct ipn_network *ipnn=from->ipn;
26 struct ipn_hash *vdeh=(struct ipn_hash *)ipnn->proto_private;
27 int port;
28 struct ethhdr *ehdr=(struct ethhdr *)msgitem->data;
29 if (msgitem->len < sizeof(struct ethhdr))
30 return 0;
31 if (!IS_BROADCAST(ehdr->h_source))
32 ipn_hash_add(vdeh,(u16 *)&ehdr->h_source,0,from->portno);
33 if (IS_BROADCAST(ehdr->h_dest) ||
34 (port = ipn_hash_find(vdeh,(u16 *)&ehdr->h_dest,0)) < 0) {
35 /*printk("SWITCH FROM %d -> BROADCAST\n",from->portno);*/
36 struct ipn_node *ipn_node;
37 list_for_each_entry(ipn_node, &ipnn->connectqueue, nodelist) {
38 if (ipn_node != from)
39 ipn_proto_sendmsg(ipn_node,msgitem);
41 } else {
42 /*printk("SWITCH FROM %d -> %d\n",from->portno,port);*/
43 ipn_proto_sendmsg(ipnn->connport[port],msgitem);
45 return 0;
48 static void ipn_kvde_switch_delport(struct ipn_node *oldport) {
49 struct ipn_network *ipnn=oldport->ipn;
50 struct ipn_hash *vdeh=(struct ipn_hash *)ipnn->proto_private;
51 ipn_hash_flush_port(vdeh,oldport->portno);
54 static int ipn_kvde_switch_newnet(struct ipn_network *newnet) {
55 struct ipn_hash *vdeh=kmem_cache_alloc(kvde_net_cache,GFP_KERNEL);
56 if (!vdeh)
57 return -ENOMEM;
58 if (!try_module_get(THIS_MODULE))
59 return -EINVAL;
60 newnet->proto_private=vdeh;
61 ipn_hash_new(vdeh,256,30);
62 return 0;
65 static void ipn_kvde_switch_delnet(struct ipn_network *oldnet) {
66 struct ipn_hash *vdeh=(struct ipn_hash *) oldnet->proto_private;
67 ipn_hash_free(vdeh);
68 kmem_cache_free(kvde_net_cache,vdeh);
69 module_put(THIS_MODULE);
72 static int ipn_kvde_switch_setsockopt(struct ipn_node *port,int optname,
73 char __user *optval, int optlen) {return -EOPNOTSUPP;}
74 static int ipn_kvde_switch_getsockopt(struct ipn_node *port,int optname,
75 char __user *optval, int *optlen) {return -EOPNOTSUPP;}
76 static int ipn_kvde_switch_ioctl(struct ipn_node *port,unsigned int request,
77 unsigned long arg) {return -EOPNOTSUPP;}
79 /* static void ipn_kvde_switch_postnewport(struct ipn_node *newport) {} */
80 /* static void ipn_kvde_switch_predelport(struct ipn_node *oldport) {} */
81 static struct ipn_protocol vde_switch_proto={
82 .ipn_p_newport=ipn_kvde_switch_newport,
83 .ipn_p_handlemsg=ipn_kvde_switch_handlemsg,
84 .ipn_p_delport=ipn_kvde_switch_delport,
85 /*.ipn_p_postnewport=ipn_kvde_switch_postnewport,*/
86 /*.ipn_p_predelport=ipn_kvde_switch_predelport,*/
87 .ipn_p_newnet=ipn_kvde_switch_newnet,
88 .ipn_p_delnet=ipn_kvde_switch_delnet,
89 .ipn_p_setsockopt=ipn_kvde_switch_setsockopt,
90 .ipn_p_getsockopt=ipn_kvde_switch_getsockopt,
91 .ipn_p_ioctl=ipn_kvde_switch_ioctl
95 static int kvde_switch_init(void)
97 int rc=0;
98 kvde_net_cache=kmem_cache_create("kvde_net",sizeof(struct ipn_hash),0,0,NULL);
99 if (!kvde_net_cache) {
100 rc=-ENOMEM;
101 goto out;
103 rc=ipn_proto_register(IPN_VDESWITCH,&vde_switch_proto);
104 out:
105 return rc;
108 static void kvde_switch_exit(void)
110 ipn_proto_deregister(IPN_VDESWITCH);
111 if(kvde_net_cache)
112 kmem_cache_destroy(kvde_net_cache);
115 module_init(kvde_switch_init);
116 module_exit(kvde_switch_exit);