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, &eth_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 + -
显示快捷键?