vnet.c
来自「xen虚拟机源代码安装包」· C语言 代码 · 共 700 行 · 第 1/2 页
C
700 行
for(i=0; i<n; i++){ err = Vnet_alloc(&vnet); if(err) break; vnetid = VNET_VIF + i; vnet->vnet = toVnetId(vnetid); snprintf(vnet->device, sizeof(vnet->device), "vnif%04x", vnetid); vnet->security = (vnetid > 10 ? security : 0); err = Vnet_create(vnet); Vnet_decref(vnet); if(err) break; } return err;}/** Initialize the vnet table and the physical vnet. * * @return 0 on success, error code otherwise */int vnet_init(void){ int err = 0; err = vnet_forward_init(); if(err) goto exit; err = vnet_table_init(); if(err) goto exit; err = vnet_setup(); if(err) goto exit; err = vif_init(); if(err) goto exit; err = varp_init(); exit: return err;}void vnet_exit(void){ varp_exit(); vif_exit(); vnet_table_free(); vnet_forward_exit();}#ifdef __KERNEL__inline int _skb_xmit(struct sk_buff *skb, uint32_t saddr){ int err = 0; struct rtable *rt = NULL; dprintf("> src=%u.%u.%u.%u dst=%u.%u.%u.%u\n", NIPQUAD(skb->nh.iph->saddr), NIPQUAD(skb->nh.iph->daddr)); skb->protocol = htons(ETH_P_IP); if(saddr){ skb->nh.iph->saddr = 0; } err = skb_route(skb, &rt); if(err){ wprintf("> skb_route=%d\n", err); wprintf("> dev=%s idx=%d src=%u.%u.%u.%u dst=%u.%u.%u.%u tos=%d\n", (skb->dev ? skb->dev->name : "???"), (skb->dev ? skb->dev->ifindex : -1), NIPQUAD(skb->nh.iph->saddr), NIPQUAD(skb->nh.iph->daddr), skb->nh.iph->tos); goto exit; } dst_release(skb->dst); skb->dst = &rt->u.dst; if(!skb->dev){ skb->dev = rt->u.dst.dev; } ip_select_ident(skb->nh.iph, &rt->u.dst, NULL); if(saddr){ skb->nh.iph->saddr = saddr; } else { if(!skb->nh.iph->saddr){ skb->nh.iph->saddr = rt->rt_src; } } ip_send_check(skb->nh.iph);#if 1 // Output to skb destination. Will use ip_output(), which fragments. // Slightly slower than neigh_compat_output() (marginal - 1%). err = dst_output(skb); #else // Sends direct to device via dev_queue_xmit(). No fragmentation? err = neigh_compat_output(skb);#endif#if 0 if(needs_frags){ err = ip_fragment(skb, ip_finish_output); } else { err = ip_finish_output(skb); }#endif exit: dprintf("< err=%d\n", err); return err;}#else extern int _skb_xmit(struct sk_buff *skb, uint32_t saddr);#endifint skb_xmit(struct sk_buff *skb){ if(MULTICAST(skb->nh.iph->daddr)){ vnet_forward_send(skb); } return _skb_xmit(skb, 0);}/** Called when a vif sends a packet to the network. * Encapsulates the packet for its vnet and forwards it. * * @param skb packet * @return 0 on success, error code otherwise * */int vnet_skb_send(struct sk_buff *skb, VnetId *vnet){ VnetId vnet_phys = toVnetId(VNET_PHYS); int err = 0; //dprintf(">\n"); skb->dev = NULL; if(!vnet || VnetId_eq(vnet, &vnet_phys)){ // No vnet or physical vnet, send direct to the network. skb_xmit(skb); } else { // Update the vif table with the source MAC. vif_update(vnet, (Vmac*)eth_hdr(skb)->h_source); err = varp_output(skb, vnet); } //dprintf("< err=%d\n", err); return err;}/** Receive an skb for a vnet. * We make the skb come out of the vif for the vnet, and * let ethernet bridging forward it to related interfaces. * * The packet must have skb->mac.raw set and skb->data must point * after the device (ethernet) header. * * Return code 1 means we now own the packet - the caller must not free it. * Return code < 0 means an error - caller still owns the packet. * * @param skb packet * @param vnet packet vnet */int vnet_skb_recv(struct sk_buff *skb, Vnet *vnet){ int err = 1; if(!vnet->dev){ // No device for the vnet. err = -ENOTCONN; goto exit; } skb->dev = vnet->dev; vnet->stats.rx_packets++; vnet->stats.rx_bytes += skb->len; netif_rx(skb); exit: return err;}/** Check that a context has the correct properties w.r.t. a vnet. * The context must be secure if the vnet requires security. * * @param vnet vnet id * @param context context * @return 0 on success, error code otherwise * * @todo Need to check that the sa provides the correct security level. */int vnet_check_context(VnetId *vnet, SkbContext *context, Vnet **val){ int err = 0; Vnet *info = NULL; SAState *sa = NULL; err = Vnet_lookup(vnet, &info); if(err){ goto exit; } if(!info->security) goto exit; err = -EINVAL; if(!context){ wprintf("> No security context\n"); goto exit; } if(context->protocol != IPPROTO_ESP){ wprintf("> Invalid protocol: wanted %d, got %d\n", IPPROTO_ESP, context->protocol); goto exit; } sa = context->data; //todo: Check security properties of the SA are correct w.r.t. the vnet. //Something like sa->security == info->security; err = 0; exit: *val = info; return err;}/** Create a tunnel for a vnet to a given address. * * @param vnet vnet id * @param addr destination address * @param tunnel return parameter * @return 0 on success, error code otherwise */static int vnet_tunnel_create(VnetId *vnet, VarpAddr *addr, Tunnel **tunnel){ int err = 0; Vnet *info = NULL; Tunnel *base = NULL; Tunnel *sa_tunnel = NULL; Tunnel *eth_tunnel = NULL; err = Vnet_lookup(vnet, &info); if(err) goto exit; if(info->security){ err = sa_tunnel_create(info, addr, base, &sa_tunnel); if(err) goto exit; base = sa_tunnel; } err = etherip_tunnel_create(vnet, addr, base, ð_tunnel); exit: Tunnel_decref(sa_tunnel); Vnet_decref(info); *tunnel = (err ? NULL : eth_tunnel); return err;}/** Lookup a tunnel for a vnet to a given address. * Uses an existing tunnel if there is one. * * @param vnet vnet id * @param addr care-of address * @param tunnel return parameter * @return 0 on success, error code otherwise */int vnet_tunnel_lookup(VnetId *vnet, VarpAddr *addr, Tunnel **tunnel){ int err = 0; err = Tunnel_lookup(vnet, addr, tunnel); if(err){ err = Tunnel_open(vnet, addr, vnet_tunnel_create, tunnel); } return err;}/** Send a packet on the appropriate tunnel. * * @param vnet vnet * @param addr tunnel endpoint * @param skb packet * @return 0 on success, error code otherwise */int vnet_tunnel_send(VnetId *vnet, VarpAddr *addr, struct sk_buff *skb){ int err = 0; Tunnel *tunnel = NULL; err = vnet_tunnel_lookup(vnet, addr, &tunnel); if(err) { char vnetbuf[VNET_ID_BUF]; char addrbuf[VARP_ADDR_BUF]; wprintf("No tunnel: skb=%p vnet=%s addr=%s\n", skb, VnetId_ntoa(vnet, vnetbuf), VarpAddr_ntoa(addr, addrbuf)); goto exit; } err = Tunnel_send(tunnel, skb); Tunnel_decref(tunnel); exit: return err;}#ifdef __KERNEL__/** Module parameter for vnet encapsulation. */static char *vnet_encaps = NULL;static void __exit vnet_module_exit(void){ ProcFS_exit(); sa_table_exit(); vnet_exit(); esp_module_exit(); etherip_module_exit(); tunnel_module_exit(); random_module_exit();}/** Initialize the vnet module. * Failure is fatal. * * @return 0 on success, error code otherwise */static int __init vnet_module_init(void){ int err = 0; if(vnet_encaps && !strcmp(vnet_encaps, "udp")){ etherip_in_udp = 1; } dprintf(">\n"); err = random_module_init(); if(err) wprintf("> random_module_init err=%d\n", err); if(err) goto exit; err = tunnel_module_init(); if(err) wprintf("> tunnel_module_init err=%d\n", err); if(err) goto exit; err = etherip_module_init(); if(err) wprintf("> etherip_module_init err=%d\n", err); if(err) goto exit; err = esp_module_init(); if(err) wprintf("> esp_module_init err=%d\n", err); if(err) goto exit; err = vnet_init(); if(err) wprintf("> vnet_init err=%d\n", err); if(err) goto exit; sa_algorithm_probe_all(); err = sa_table_init(); if(err) wprintf("> sa_table_init err=%d\n", err); if(err) goto exit; ProcFS_init(); exit: if(err < 0){ vnet_module_exit(); wprintf("< err=%d\n", err); } return err;}module_init(vnet_module_init);module_exit(vnet_module_exit);MODULE_LICENSE("GPL");module_param(vnet_encaps, charp, 0644);MODULE_PARM_DESC(vnet_encaps, "Vnet encapsulation: etherip or udp.");#endif
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?