- unsigned int CPU_ID = smp_processor_id();
-
- eth = (struct ethhdr *) (skb->data);
-
- /* Only route ethernet IP packets */
- if (eth->h_proto == __constant_htons(ETH_P_IP)) {
- iph = (struct iphdr *) (skb->data + ETH_HLEN);
-
- /* Generate the hash value */
- hash = ((*(u8 *) &iph->daddr) ^ (*(u8 *) & iph->saddr)) & NETDEV_FASTROUTE_HMASK;
-
- rt = (struct rtable *) (dev->fastpath[hash]);
- if (rt != NULL
- && ((*(u32 *) &iph->daddr) == (*(u32 *) &rt->key.dst))
- && ((*(u32 *) &iph->saddr) == (*(u32 *) &rt->key.src))
- && !(rt->u.dst.obsolete)) {
- odev = rt->u.dst.dev;
- netdev_rx_stat[CPU_ID].fastroute_hit++;
-
- /* Make sure the packet is:
- * 1) IPv4
- * 2) without any options (header length of 5)
- * 3) Not a multicast packet
- * 4) going to a valid destination
- * 5) Not out of time-to-live
- */
- if (iph->version == 4
- && iph->ihl == 5
- && (!(eth->h_dest[0] & 0x01))
- && neigh_is_valid(rt->u.dst.neighbour)
- && iph->ttl > 1) {
-
- /* Fast Route Path: Taken if the outgoing device is ready to transmit the packet now */
- if ((!netif_queue_stopped(odev))
- && (!spin_is_locked(odev->xmit_lock))
- && (skb->len <= (odev->mtu + ETH_HLEN + 2 + 4))) {
-
- skb->pkt_type = PACKET_FASTROUTE;
- skb->protocol = __constant_htons(ETH_P_IP);
- ip_decrease_ttl(iph);
- memcpy(eth->h_source, odev->dev_addr, MAC_ADDR_LEN);
- memcpy(eth->h_dest, rt->u.dst.neighbour->ha, MAC_ADDR_LEN);
- skb->dev = odev;
-
- /* Prep the skb for the packet */
- skb_put(skb, length);
-
- if (odev->hard_start_xmit(skb, odev) != 0) {
- panic("%s: FastRoute path corrupted", dev->name);
- }
- netdev_rx_stat[CPU_ID].fastroute_success++;
- }
-
- /* Semi Fast Route Path: Mark the packet as needing fast routing, but let the
- * stack handle getting it to the device */
- else {
- skb->pkt_type = PACKET_FASTROUTE;
- skb->nh.raw = skb->data + ETH_HLEN;
- skb->protocol = __constant_htons(ETH_P_IP);
- netdev_rx_stat[CPU_ID].fastroute_defer++;
-
- /* Prep the skb for the packet */
- skb_put(skb, length);
-
- if(RECEIVE(skb) == NET_RX_DROP) {
- priv->extra_stats.kernel_dropped++;
- }
- }
-
- return 1;
- }
- }
- }
-#endif /* CONFIG_NET_FASTROUTE */
- return 0;