ia64/xen-unstable

view tools/vnet/vnet-module/vnet.c @ 8740:3d7ea7972b39

Update patches for linux 2.6.15.

Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
author cl349@firebug.cl.cam.ac.uk
date Thu Feb 02 17:16:00 2006 +0000 (2006-02-02)
parents 06d84bf87159
children 71b0f00f6344
line source
1 /*
2 * Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free software Foundation, Inc.,
16 * 59 Temple Place, suite 330, Boston, MA 02111-1307 USA
17 *
18 */
20 #include <linux/config.h>
21 #include <linux/module.h>
22 #include <linux/types.h>
23 #include <linux/kernel.h>
24 #include <linux/version.h>
25 #include <linux/errno.h>
27 #include <linux/string.h>
29 #include <linux/net.h>
30 #include <linux/in.h>
31 #include <linux/inet.h>
32 #include <linux/netdevice.h>
34 #include <linux/etherdevice.h>
35 #include <net/ip.h>
36 #include <net/protocol.h>
37 #include <net/route.h>
38 #include <linux/skbuff.h>
39 #include <net/checksum.h>
41 #include <tunnel.h>
42 #include <sa.h>
43 #include <varp.h>
44 #include <if_varp.h>
45 #include <esp.h>
46 #include <etherip.h>
47 #include <random.h>
48 #include <tunnel.h>
50 #include <skb_util.h>
51 #include <vnet_dev.h>
52 #include <vnet.h>
53 #include <vif.h>
54 #include <vnet_ioctl.h>
55 #include <sa_algorithm.h>
57 #include "allocate.h"
58 #include "hash_table.h"
59 #include "sys_net.h"
60 #include "sys_string.h"
62 #define MODULE_NAME "VNET"
63 #define DEBUG 1
64 #undef DEBUG
65 #include "debug.h"
67 /** Default vnet security level.
68 */
69 int vnet_security_default = SA_AUTH ; //| SA_CONF;
71 /** Key for entries in the vnet address table. */
72 typedef struct VnetAddrKey {
73 /** Vnet id. */
74 VnetId vnet;
75 /** MAC address. */
76 unsigned char mac[ETH_ALEN];
77 } VnetAddrKey;
79 /** The physical vnet. */
80 Vnet *vnet_physical = NULL;
82 /** Table of vnets indexed by id. */
83 static HashTable *vnet_table = NULL;
85 /** Decrement reference count, freeing if zero.
86 *
87 * @param info vnet (OK if null)
88 */
89 void Vnet_decref(Vnet *info){
90 if(!info) return;
91 if(atomic_dec_and_test(&info->refcount)){
92 vnet_dev_remove(info);
93 deallocate(info);
94 }
95 }
97 /** Increment reference count.
98 *
99 * @param info vnet (OK if null)
100 */
101 void Vnet_incref(Vnet *info){
102 if(!info) return;
103 atomic_inc(&info->refcount);
104 }
106 void Vnet_print(Vnet *info)
107 {
108 char vnetbuf[VNET_ID_BUF];
110 printk(KERN_INFO "VNET(vnet=%s device=%s security=%c%c)\n",
111 VnetId_ntoa(&info->vnet, vnetbuf),
112 info->device,
113 ((info->security & SA_AUTH) ? 'a' : '-'),
114 ((info->security & SA_CONF) ? 'c' : '-'));
115 }
117 void vnet_print(void)
118 {
119 HashTable_for_decl(entry);
120 Vnet *info;
122 HashTable_for_each(entry, vnet_table){
123 info = entry->value;
124 Vnet_print(info);
125 }
126 }
128 /** Allocate a vnet, setting reference count to 1.
129 *
130 * @param info return parameter for vnet
131 * @return 0 on success, error code otherwise
132 */
133 int Vnet_alloc(Vnet **info){
134 int err = 0;
135 *info = ALLOCATE(Vnet);
136 if(*info){
137 atomic_set(&(*info)->refcount, 1);
138 } else {
139 err = -ENOMEM;
140 }
141 return err;
142 }
144 /** Add a vnet to the table under its vnet id.
145 *
146 * @param info vnet to add
147 * @return 0 on success, error code otherwise
148 */
149 int Vnet_add(Vnet *info){
150 int err = 0;
151 HTEntry *entry = NULL;
152 // Vnet_del(info->vnet); //todo: Delete existing vnet info?
153 Vnet_incref(info);
154 entry = HashTable_add(vnet_table, &info->vnet, info);
155 if(!entry){
156 err = -ENOMEM;
157 Vnet_decref(info);
158 }
159 return err;
160 }
162 /** Remove a vnet from the table.
163 *
164 * @param vnet id of vnet to remove
165 * @return number of vnets removed
166 */
167 int Vnet_del(VnetId *vnet){
168 return HashTable_remove(vnet_table, vnet);
169 }
171 /** Lookup a vnet by id.
172 * References the vnet on success - the caller must decref.
173 *
174 * @param vnet vnet id
175 * @param info return parameter for vnet
176 * @return 0 on sucess, -ENOENT if no vnet found
177 */
178 int Vnet_lookup(VnetId *vnet, Vnet **info){
179 int err = 0;
180 *info = HashTable_get(vnet_table, vnet);
181 if(*info){
182 Vnet_incref(*info);
183 } else {
184 err = -ENOENT;
185 }
186 return err;
187 }
189 /** Free an entry in the vnet table.
190 *
191 * @param table containing table
192 * @param entry to free
193 */
194 static void vnet_entry_free_fn(HashTable *table, HTEntry *entry){
195 Vnet *info;
196 if(!entry) return;
197 info = entry->value;
198 if(info){
199 vnet_dev_remove(info);
200 Vnet_decref(info);
201 }
202 HTEntry_free(entry);
203 }
205 /** Setup some vnet entries (for testing).
206 * Vnet 1 is physical, vnets 2 to 10 are insecure, vnets above
207 * 10 are secure.
208 *
209 * @return 0 on success, negative error code otherwise
210 */
211 static int vnet_setup(void){
212 int err = 0;
213 int i, n = 3;
214 int security = vnet_security_default;
215 uint32_t vnetid;
216 Vnet *vnet;
218 for(i=0; i<n; i++){
219 err = Vnet_alloc(&vnet);
220 if(err) break;
221 vnetid = VNET_VIF + i;
222 vnet->vnet = toVnetId(vnetid);
223 sprintf(vnet->device, "vnif%04x", vnetid);
224 vnet->security = (vnetid > 10 ? security : 0);
225 err = Vnet_create(vnet);
226 if(err) break;
227 }
228 return err;
229 }
231 int vnet_key_equal_fn(void *k1, void *k2){
232 VnetId *key1 = k1;
233 VnetId *key2 = k2;
234 return VnetId_eq(key1, key2);
235 }
237 Hashcode vnet_key_hash_fn(void *k){
238 VnetId *key = k;
239 return VnetId_hash(0, key);
240 }
242 /** Initialize the vnet table and the physical vnet.
243 *
244 * @return 0 on success, error code otherwise
245 */
246 int vnet_init(void){
247 int err = 0;
249 vnet_table = HashTable_new(0);
250 if(!vnet_table){
251 err = -ENOMEM;
252 goto exit;
253 }
254 vnet_table->key_equal_fn = vnet_key_equal_fn;
255 vnet_table->key_hash_fn = vnet_key_hash_fn;
256 vnet_table->entry_free_fn = vnet_entry_free_fn;
258 err = Vnet_alloc(&vnet_physical);
259 if(err) goto exit;
260 vnet_physical->vnet = toVnetId(VNET_PHYS);
261 vnet_physical->security = 0;
262 err = Vnet_add(vnet_physical);
263 if(err) goto exit;
264 err = vnet_setup();
265 if(err) goto exit;
266 err = varp_init();
267 if(err) goto exit;
268 err = vif_init();
269 exit:
270 return err;
271 }
273 void vnet_exit(void){
274 vif_exit();
275 varp_exit();
276 HashTable_free(vnet_table);
277 vnet_table = NULL;
278 }
280 inline int skb_xmit(struct sk_buff *skb){
281 int err = 0;
282 struct rtable *rt = NULL;
284 dprintf(">\n");
285 skb->protocol = htons(ETH_P_IP);
286 err = skb_route(skb, &rt);
287 if(err){
288 wprintf("> skb_route=%d\n", err);
289 wprintf("> dev=%s idx=%d src=%u.%u.%u.%u dst=%u.%u.%u.%u tos=%d\n",
290 (skb->dev ? skb->dev->name : "???"),
291 (skb->dev ? skb->dev->ifindex : -1),
292 NIPQUAD(skb->nh.iph->saddr),
293 NIPQUAD(skb->nh.iph->daddr),
294 skb->nh.iph->tos);
296 goto exit;
297 }
298 skb->dst = &rt->u.dst;
299 if(!skb->dev){
300 skb->dev = rt->u.dst.dev;
301 }
303 ip_select_ident(skb->nh.iph, &rt->u.dst, NULL);
305 if(skb->nh.iph->saddr == 0){
306 skb->nh.iph->saddr = rt->rt_src;
307 }
309 skb->nh.iph->check = 0;
310 skb->nh.iph->check = ip_compute_csum(skb->nh.raw, (skb->nh.iph->ihl << 2));
312 err = neigh_compat_output(skb);
314 exit:
315 dprintf("< err=%d\n", err);
316 return err;
317 }
319 /** Called when a vif sends a packet to the network.
320 * Encapsulates the packet for its vnet and forwards it.
321 *
322 * @param skb packet
323 * @return 0 on success, error code otherwise
324 *
325 * @todo fixme
326 */
327 int vnet_skb_send(struct sk_buff *skb, VnetId *vnet){
328 int err = 0;
329 VnetId vnet_phys = toVnetId(VNET_PHYS);
331 dprintf(">\n");
332 skb->dev = NULL;
333 if(!vnet || VnetId_eq(vnet, &vnet_phys)){
334 // No vnet or physical vnet, send direct to the network.
335 skb_xmit(skb);
336 } else {
337 err = varp_output(skb, vnet);
338 }
339 dprintf("< err=%d\n", err);
340 return err;
341 }
343 /** Receive an skb for a vnet.
344 * We make the skb come out of the vif for the vnet, and
345 * let ethernet bridging forward it to related interfaces.
346 * If the dest is broadcast, goes to all vifs on the vnet.
347 * If the dest is unicast, goes to the addressed vif on the vnet.
348 *
349 * The packet must have skb->mac.raw set and skb->data must point
350 * after the device (ethernet) header.
351 *
352 * @param skb packet
353 * @param vnet packet vnet
354 * @param vmac packet vmac
355 * @return 0 on success, error code otherwise
356 */
357 int vnet_skb_recv(struct sk_buff *skb, VnetId *vnet, Vmac *vmac){
358 int err = 0;
359 Vnet *info = NULL;
361 err = Vnet_lookup(vnet, &info);
362 if(err) goto exit;
363 skb->dev = info->dev;
364 netif_rx(skb);
365 exit:
366 if(info) Vnet_decref(info);
367 if(err){
368 kfree_skb(skb);
369 }
370 return err;
371 }
373 /** Determine ESP security mode for a new SA.
374 *
375 * @param spi incoming spi
376 * @param protocol incoming protocol
377 * @param addr source address
378 * @return security level or negative error code
379 *
380 * @todo Need to check spi, and do some lookup for security params.
381 */
382 int vnet_sa_security(u32 spi, int protocol, u32 addr){
383 int security = vnet_security_default;
384 dprintf("< security=%x\n", security);
385 return security;
386 }
388 /** Create a new SA for incoming traffic.
389 *
390 * @param spi incoming spi
391 * @param protocol incoming protocol
392 * @param addr source address
393 * @param sa return parameter for SA
394 * @return 0 on success, error code otherwise
395 */
396 int vnet_sa_create(u32 spi, int protocol, u32 addr, SAState **sa){
397 int err = 0;
398 int security = vnet_sa_security(spi, protocol, addr);
399 if(security < 0){
400 err = security;
401 goto exit;
402 }
403 err = sa_create(security, spi, protocol, addr, sa);
404 exit:
405 return err;
406 }
408 /** Check that a context has the correct properties w.r.t. a vnet.
409 * The context must be secure if the vnet requires security.
410 *
411 * @param vnet vnet id
412 * @param context context
413 * @return 0 on success, error code otherwise
414 *
415 * @todo Need to check that the sa provides the correct security level.
416 */
417 int vnet_check_context(VnetId *vnet, SkbContext *context, Vnet **val){
418 int err = 0;
419 Vnet *info = NULL;
420 SAState *sa = NULL;
422 err = Vnet_lookup(vnet, &info);
423 if(err){
424 goto exit;
425 }
426 if(!info->security) goto exit;
427 err = -EINVAL;
428 if(!context){
429 wprintf("> No security context\n");
430 goto exit;
431 }
432 if(context->protocol != IPPROTO_ESP){
433 wprintf("> Invalid protocol: wanted %d, got %d\n",
434 IPPROTO_ESP, context->protocol);
435 goto exit;
436 }
437 sa = context->data;
438 //todo: Check security properties of the SA are correct w.r.t. the vnet.
439 //Something like sa->security == info->security;
440 err = 0;
441 exit:
442 *val = info;
443 return err;
444 }
446 /** Open function for SA tunnels.
447 *
448 * @param tunnel to open
449 * @return 0 on success, error code otherwise
450 */
451 static int sa_tunnel_open(Tunnel *tunnel){
452 int err = 0;
453 //dprintf(">\n");
454 //dprintf("< err=%d\n", err);
455 return err;
456 }
458 /** Close function for SA tunnels.
459 *
460 * @param tunnel to close (OK if null)
461 */
462 static void sa_tunnel_close(Tunnel *tunnel){
463 SAState *sa;
464 if(!tunnel) return;
465 sa = tunnel->data;
466 if(!sa) return;
467 SAState_decref(sa);
468 tunnel->data = NULL;
469 }
471 /** Packet send function for SA tunnels.
472 *
473 * @param tunnel to send on
474 * @param skb packet to send
475 * @return 0 on success, negative error code on error
476 */
477 static int sa_tunnel_send(Tunnel *tunnel, struct sk_buff *skb){
478 int err = -EINVAL;
479 SAState *sa;
480 if(!tunnel){
481 wprintf("> Null tunnel!\n");
482 goto exit;
483 }
484 sa = tunnel->data;
485 if(!sa){
486 wprintf("> Null SA!\n");
487 goto exit;
488 }
489 err = SAState_send(sa, skb, tunnel->base);
490 exit:
491 return err;
492 }
494 /** Functions used by SA tunnels. */
495 static TunnelType _sa_tunnel_type = {
496 .name = "SA",
497 .open = sa_tunnel_open,
498 .close = sa_tunnel_close,
499 .send = sa_tunnel_send
500 };
502 /** Functions used by SA tunnels. */
503 TunnelType *sa_tunnel_type = &_sa_tunnel_type;
505 /** Open a tunnel for a vnet to a given address.
506 *
507 * @param vnet vnet id
508 * @param addr destination address
509 * @param tunnel return parameter
510 * @return 0 on success, error code otherwise
511 */
512 int vnet_tunnel_open(VnetId *vnet, VarpAddr *addr, Tunnel **tunnel){
513 extern TunnelType *etherip_tunnel_type;
514 int err = 0;
515 Vnet *info = NULL;
516 Tunnel *base_tunnel = NULL;
517 Tunnel *sa_tunnel = NULL;
518 Tunnel *etherip_tunnel = NULL;
520 err = Vnet_lookup(vnet, &info);
521 if(err) goto exit;
522 if(info->security){
523 SAState *sa = NULL;
524 //FIXME: Assuming IPv4 for now.
525 u32 ipaddr = addr->u.ip4.s_addr;
526 err = Tunnel_create(sa_tunnel_type, vnet, addr, base_tunnel, &sa_tunnel);
527 if(err) goto exit;
528 err = sa_create(info->security, 0, IPPROTO_ESP, ipaddr, &sa);
529 if(err) goto exit;
530 sa_tunnel->data = sa;
531 base_tunnel = sa_tunnel;
532 }
533 err = Tunnel_create(etherip_tunnel_type, vnet, addr, base_tunnel, &etherip_tunnel);
534 if(err) goto exit;
535 err = Tunnel_add(etherip_tunnel);
536 exit:
537 Tunnel_decref(sa_tunnel);
538 Vnet_decref(info);
539 if(err){
540 *tunnel = NULL;
541 } else {
542 *tunnel = etherip_tunnel;
543 }
544 return err;
545 }
547 /** Lookup a tunnel for a vnet to a given address.
548 * Uses an existing tunnel if there is one.
549 *
550 * @param vnet vnet id
551 * @param addr care-of address
552 * @param tunnel return parameter
553 * @return 0 on success, error code otherwise
554 */
555 int vnet_tunnel_lookup(VnetId *vnet, VarpAddr *addr, Tunnel **tunnel){
556 int err = 0;
557 *tunnel = Tunnel_lookup(vnet, addr);
558 if(!*tunnel){
559 err = vnet_tunnel_open(vnet, addr, tunnel);
560 }
561 return err;
562 }
564 /** Send a packet on the appropriate tunnel.
565 *
566 * @param vnet vnet
567 * @param addr tunnel endpoint
568 * @param skb packet
569 * @return 0 on success, error code otherwise
570 */
571 int vnet_tunnel_send(VnetId *vnet, VarpAddr *addr, struct sk_buff *skb){
572 int err = 0;
573 Tunnel *tunnel = NULL;
574 err = vnet_tunnel_lookup(vnet, addr, &tunnel);
575 if(err) goto exit;
576 err = Tunnel_send(tunnel, skb);
577 Tunnel_decref(tunnel);
578 exit:
579 return err;
580 }
582 static void __exit vnet_module_exit(void){
583 ProcFS_exit();
584 sa_table_exit();
585 vnet_exit();
586 esp_module_exit();
587 etherip_module_exit();
588 tunnel_module_exit();
589 random_module_exit();
590 }
592 /** Initialize the vnet module.
593 * Failure is fatal.
594 *
595 * @return 0 on success, error code otherwise
596 */
597 static int __init vnet_module_init(void){
598 int err = 0;
600 dprintf(">\n");
601 err = random_module_init();
602 if(err) wprintf("> random_module_init err=%d\n", err);
603 if(err) goto exit;
604 err = tunnel_module_init();
605 if(err) wprintf("> tunnel_module_init err=%d\n", err);
606 if(err) goto exit;
607 err = etherip_module_init();
608 if(err) wprintf("> etherip_module_init err=%d\n", err);
609 if(err) goto exit;
610 err = esp_module_init();
611 if(err) wprintf("> esp_module_init err=%d\n", err);
612 if(err) goto exit;
613 err = vnet_init();
614 if(err) wprintf("> vnet_init err=%d\n", err);
615 if(err) goto exit;
616 sa_algorithm_probe_all();
617 err = sa_table_init();
618 if(err) wprintf("> sa_table_init err=%d\n", err);
619 if(err) goto exit;
620 ProcFS_init();
621 exit:
622 if(err < 0){
623 vnet_module_exit();
624 wprintf("< err=%d\n", err);
625 }
626 return err;
627 }
629 module_init(vnet_module_init);
630 module_exit(vnet_module_exit);
631 MODULE_LICENSE("GPL");