Index: freevps/s_context_network.c =================================================================== RCS file: /home/cvs/kernel_26/freevps/s_context_network.c,v retrieving revision 1.25.2.7 diff -u -r1.25.2.7 s_context_network.c --- freevps/s_context_network.c 21 Apr 2006 11:04:19 -0000 1.25.2.7 +++ freevps/s_context_network.c 17 May 2006 11:41:50 -0000 @@ -817,8 +817,7 @@ static inline void s_context_assign_virtual(struct net_device *dev) { if (!(dev->priv_flags & IFF_VIRTUAL)) { - if( dev->dev_hard_start_xmit == NULL ) - { + if (dev->dev_hard_start_xmit == NULL) { dev->dev_hard_start_xmit = dev->hard_start_xmit; dev->hard_start_xmit = &s_context_hard_start_xmit; }else @@ -844,8 +843,7 @@ me need use UP not a REGISTER because many drivers not assign dev->hard_start_xmit before register_netdevice. */ - if( dev->type != ARPHRD_LOOPBACK ) - { + if (dev->type != ARPHRD_LOOPBACK) { s_context_assign_virtual(dev); } break; @@ -901,6 +899,7 @@ return 0; } + long sys_s_context_network(int32_t ctx_id, int32_t cmd, char __user *ifname, void __user *data) { Index: freevps/s_context_vnetdev.c =================================================================== RCS file: /home/cvs/kernel_26/freevps/s_context_vnetdev.c,v retrieving revision 1.9.2.5 diff -u -r1.9.2.5 s_context_vnetdev.c --- freevps/s_context_vnetdev.c 21 Apr 2006 11:04:19 -0000 1.9.2.5 +++ freevps/s_context_vnetdev.c 17 May 2006 11:42:27 -0000 @@ -1,10 +1,18 @@ #include #include +#include +#include + #include #include #include #include +/**************************************************************************************************************/ +DEFINE_RWLOCK(vnet_lock); +#define FREEVPS_VNET_ID 0xAA55 +/**************************************************************************************************************/ + /* transmit packet thru host network device */ static int vnetdev_tx(struct sk_buff *skb) { @@ -34,13 +42,17 @@ skb->dev = dev->host; rc = dev_queue_xmit(skb); - +#if 0 if (rc == NET_XMIT_SUCCESS) { vnetdev->stats.tx_bytes += size; vnetdev->stats.tx_packets++; } else { vnetdev->stats.tx_dropped++; } +#endif + if (rc != NET_XMIT_SUCCESS) { + vnetdev->stats.tx_dropped++; + } return rc; } @@ -477,7 +489,7 @@ /* setup data field of device */ dev->flags = host->flags; - dev->flags &= ~(IFF_UP | IFF_MULTICAST); + dev->flags &= ~IFF_UP; dev->mtu = host->mtu; dev->type = host->type; @@ -486,15 +498,25 @@ dev->priv_flags |= host->priv_flags; /* set HW address */ - memcpy(dev->dev_addr, host->dev_addr, host->addr_len); +// memcpy(dev->dev_addr, host->dev_addr, host->addr_len); + random_ether_addr(dev->dev_addr); + dev->dev_addr[1] = FREEVPS_VNET_ID & 0xFF; + dev->dev_addr[2] = (FREEVPS_VNET_ID >> 16) & 0xFF; + dev->dev_addr[3] = dev->s_context->id & 0xFF; + dev->dev_addr[4] = (dev->s_context->id >>16) & 0xFF; memcpy(dev->broadcast, host->broadcast, host->addr_len); dev->addr_len = host->addr_len; + dev->watchdog_timeo = host->watchdog_timeo; /* setup device calls */ dev->get_stats = vnetdev_stats; dev->hard_header_parse = host->hard_header_parse; +/* + dev->hard_header = host->hard_header; + dev->rebuild_header = host->rebuild_header; +*/ if(host->hard_header) { dev->hard_header = vnetdev_hard_header; @@ -510,8 +532,11 @@ /* ok. all done, let's open vnetdev device */ dev->host = host; + write_lock_bh(&vnet_lock); list_add(&dev->vnet, &host->vnet); - + write_unlock_bh(&vnet_lock); + dev_set_promiscuity(host, 1); + return 0; } @@ -528,14 +553,73 @@ dev_close(dev); if (dev->host != NULL) { - dev_put(dev->host); - list_del_init(&dev->vnet); - dev->host = NULL; + dev_put(dev->host); + write_lock_bh(&vnet_lock); + list_del_init(&dev->vnet); + write_unlock_bh(&vnet_lock); + dev->host = NULL; } ctx_rtnl_unlock(s_context); - + return ret; +} + +int __netif_receive_skb(struct sk_buff *skb); + +/* based on ipt_mac */ +void s_context_find_vdev(struct sk_buff *skb) +{ + struct net_device *newdev, *dev; + struct list_head *tmp; + +// printk("find vdev1\n"); + if (!((skb->mac.raw >= skb->head) && + ((skb->mac.raw + ETH_HLEN) <= skb->data))) + return; + +// printk("find vdev2\n"); + if(skb->s_context != &root_context) + return; + +// printk("find vdev3\n"); + dev=skb->dev; + + if((eth_hdr(skb)->h_dest)[0]&1) { + read_lock(&vnet_lock); + list_for_each(tmp,&dev->vnet) { + struct sk_buff *newskb; + newdev = list_entry(tmp,struct net_device, vnet); + newskb = skb_clone(skb, GFP_ATOMIC); +// printk("bkr send to %x(%d)\n",newdev, newdev->s_context); + newskb->dev = newdev; + newskb->s_context = newdev->s_context; + count_in_traff(skb); + __netif_receive_skb(newskb); + } + read_unlock(&vnet_lock); + return; + } + +// printk("find vdev4\n"); +#define mac(x) (((x)[1]<<24)|((x)[2]<<16)|((x)[3]<<8)|((x)[4])) + if( dev->type != ARPHRD_LOOPBACK ) { + read_lock(&vnet_lock); + list_for_each(tmp,&dev->vnet) { + newdev = list_entry(tmp,struct net_device, vnet); +// printk("find vdev %x(%x) - %x\n",mac(eth_hdr(skb)->h_dest), mac(eth_hdr(skb)->h_source), mac(newdev->dev_addr) ); + if (memcmp(eth_hdr(skb)->h_dest, newdev->dev_addr, ETH_ALEN) == 0 ) { +// printk("found %p - %p\n", skb, newdev); + skb->dev = newdev; + skb->s_context = newdev->s_context; + skb->pkt_type = PACKET_HOST; + break; + } + } + read_unlock(&vnet_lock); + count_in_traff(skb); + } +#undef mac } Index: include/linux/spinlock.h =================================================================== RCS file: /home/cvs/kernel_26/include/linux/spinlock.h,v retrieving revision 1.1.1.1.2.1 diff -u -r1.1.1.1.2.1 spinlock.h --- include/linux/spinlock.h 9 Mar 2006 16:23:06 -0000 1.1.1.1.2.1 +++ include/linux/spinlock.h 17 May 2006 11:41:50 -0000 @@ -404,7 +404,7 @@ #define write_trylock(lock) _write_trylock(lock) #define DEFINE_SPINLOCK(x) spinlock_t x = SPIN_LOCK_UNLOCKED -#define DEFINE_RWLOCK(x) rw_lock_t x = RW_LOCK_UNLOCKED +#define DEFINE_RWLOCK(x) rwlock_t x = RW_LOCK_UNLOCKED /* Where's read_trylock? */ #define spin_lock(lock) _spin_lock(lock) Index: include/linux/freevps/s_context_network.h =================================================================== RCS file: /home/cvs/kernel_26/include/linux/freevps/s_context_network.h,v retrieving revision 1.9 diff -u -r1.9 s_context_network.h --- include/linux/freevps/s_context_network.h 8 Jul 2005 12:48:18 -0000 1.9 +++ include/linux/freevps/s_context_network.h 17 May 2006 11:41:50 -0000 @@ -121,10 +121,18 @@ struct net_device *dev = skb->dev; struct s_context *ctx = dev->s_context; unsigned long flags; + struct vnetdev *vnetdev; write_lock(&ctx->traf_lock); ctx->traf_in += skb-> len; write_unlock(&ctx->traf_lock); + if ((skb->dev->priv_flags) & IFF_VIRTUAL) { + vnetdev = (struct vnetdev *)dev->priv; + vnetdev_lock(vnetdev); + vnetdev->stats.rx_bytes += skb->len; + vnetdev->stats.rx_packets++; + vnetdev_unlock(vnetdev); + } }; static inline void count_out_traff(struct sk_buff *skb) @@ -139,8 +147,8 @@ if ((skb->dev->priv_flags) & IFF_VIRTUAL) { vnetdev = (struct vnetdev *)dev->priv; vnetdev_lock(vnetdev); - vnetdev->stats.rx_bytes += skb->len; - vnetdev->stats.rx_packets++; + vnetdev->stats.tx_bytes += skb->len; + vnetdev->stats.tx_packets++; vnetdev_unlock(vnetdev); } }; @@ -155,6 +163,7 @@ }; extern int s_context_hard_start_xmit(struct sk_buff *skb, struct net_device *dev); +void s_context_find_vdev(struct sk_buff *skb); /********************** *******************************/ int s_context_vnetcfg_remove(struct net_device *dev); Index: net/core/dev.c =================================================================== RCS file: /home/cvs/kernel_26/net/core/dev.c,v retrieving revision 1.9.2.2 diff -u -r1.9.2.2 dev.c --- net/core/dev.c 7 Dec 2005 10:23:59 -0000 1.9.2.2 +++ net/core/dev.c 17 May 2006 11:41:50 -0000 @@ -1620,29 +1620,12 @@ } #endif -int netif_receive_skb(struct sk_buff *skb) +/* for avoid recursive call while recerve*/ +int __netif_receive_skb(struct sk_buff *skb) { struct packet_type *ptype, *pt_prev; int ret = NET_RX_DROP; unsigned short type; - -#ifdef CONFIG_NETPOLL - if (skb->dev->netpoll_rx && skb->dev->poll && netpoll_rx(skb)) { - kfree_skb(skb); - return NET_RX_DROP; - } -#endif - - if (!skb->stamp.tv_sec) - net_timestamp(&skb->stamp); - - skb_bond(skb); - - __get_cpu_var(netdev_rx_stat).total++; - - skb->h.raw = skb->nh.raw = skb->data; - skb->mac_len = skb->nh.raw - skb->mac.raw; - pt_prev = NULL; rcu_read_lock(); @@ -1709,6 +1692,30 @@ out: rcu_read_unlock(); return ret; +} + +int netif_receive_skb(struct sk_buff *skb) +{ + +#ifdef CONFIG_NETPOLL + if (skb->dev->netpoll_rx && skb->dev->poll && netpoll_rx(skb)) { + kfree_skb(skb); + return NET_RX_DROP; + } +#endif + + if (!skb->stamp.tv_sec) + net_timestamp(&skb->stamp); + + skb_bond(skb); + + __get_cpu_var(netdev_rx_stat).total++; + + skb->h.raw = skb->nh.raw = skb->data; + skb->mac_len = skb->nh.raw - skb->mac.raw; + s_context_find_vdev(skb); + + return __netif_receive_skb(skb); } static int process_backlog(struct net_device *backlog_dev, int *budget) Index: net/ipv4/arp.c =================================================================== RCS file: /home/cvs/kernel_26/net/ipv4/arp.c,v retrieving revision 1.7.2.2 diff -u -r1.7.2.2 arp.c --- net/ipv4/arp.c 9 Mar 2006 16:23:10 -0000 1.7.2.2 +++ net/ipv4/arp.c 17 May 2006 11:41:50 -0000 @@ -249,12 +249,10 @@ spin_lock_bh(&s_context_route_lock); vps_dev = s_context_ipv4_find_route(addr); spin_unlock_bh(&s_context_route_lock); - if( vps_dev != NULL ) - { + if (vps_dev != NULL) { neigh->type = RTN_LOCAL; local = 1; - } - else + } else neigh->type = inet_addr_type(s_context, addr); rcu_read_lock(); @@ -327,10 +325,8 @@ memcpy(neigh->ha, dev->broadcast, dev->addr_len); } - if( local ) - { + if (local) neigh->ops = &arp_broken_ops; - } else if (dev->hard_header_cache) neigh->ops = &arp_hh_ops; @@ -763,8 +759,7 @@ u16 dev_type = dev->type; int addr_type; struct neighbour *n; - struct s_context *s_context; - struct net_device *newdev; + struct s_context *s_context = skb->s_context; /* arp_rcv below verifies the ARP header and verifies the device * is ARP'able. @@ -822,7 +817,6 @@ #endif #endif } - /* Understand only these message types */ if (arp->ar_op != htons(ARPOP_REPLY) && @@ -840,18 +834,9 @@ tha = arp_ptr; arp_ptr += dev->addr_len; memcpy(&tip, arp_ptr, 4); - - spin_lock(&s_context_route_lock); - newdev = s_context_ipv4_find_route(tip); - spin_unlock(&s_context_route_lock); - if( newdev != NULL ) { - skb->dev=newdev; - dev=newdev; - } - s_context = dev->s_context; - skb->s_context = s_context; - count_in_traff(skb); - + + + in_dev = in_dev_get(dev); if (in_dev == NULL) goto out; @@ -995,7 +980,7 @@ (2 * dev->addr_len) + (2 * sizeof(u32))))) goto freeskb; - + arp = skb->nh.arph; if (arp->ar_hln != dev->addr_len || dev->flags & IFF_NOARP || Index: net/ipv4/ip_input.c =================================================================== RCS file: /home/cvs/kernel_26/net/ipv4/ip_input.c,v retrieving revision 1.6.2.1 diff -u -r1.6.2.1 ip_input.c --- net/ipv4/ip_input.c 16 Feb 2006 19:36:34 -0000 1.6.2.1 +++ net/ipv4/ip_input.c 17 May 2006 11:41:50 -0000 @@ -150,7 +150,6 @@ #include #include #include -#include /* * SNMP management statistics @@ -423,17 +422,6 @@ if (skb->ip_summed == CHECKSUM_HW) skb->ip_summed = CHECKSUM_NONE; } - } - if( dev->type != ARPHRD_LOOPBACK ) - { - spin_lock(&s_context_route_lock); - newdev = s_context_ipv4_find_route(skb->nh.iph->daddr); - spin_unlock(&s_context_route_lock); - if( newdev != NULL ) { - skb->dev=newdev; - } - skb->s_context = skb->dev->s_context; - count_in_traff(skb); } return NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, skb->dev, NULL, ip_rcv_finish);