-/**********************************************************************
- * gfar_accept_fastpath
- *
- * Used to authenticate to the kernel that a fast path entry can be
- * added to device's routing table cache
- *
- * Input : pointer to ethernet interface network device structure and
- * a pointer to the designated entry to be added to the cache.
- * Output : zero upon success, negative upon failure
- **********************************************************************/
-#ifdef CONFIG_NET_FASTROUTE
-static int gfar_accept_fastpath(struct net_device *dev, struct dst_entry *dst)
-{
- struct net_device *odev = dst->dev;
-
- if ((dst->ops->protocol != __constant_htons(ETH_P_IP))
- || (odev->type != ARPHRD_ETHER)
- || (odev->accept_fastpath == NULL)) {
- return -1;
- }
-
- return 0;
-}
-#endif
-
-/* try_fastroute() -- Checks the fastroute cache to see if a given packet
- * can be routed immediately to another device. If it can, we send it.
- * If we used a fastroute, we return 1. Otherwise, we return 0.
- * Returns 0 if CONFIG_NET_FASTROUTE is not on
- */
-static inline int try_fastroute(struct sk_buff *skb, struct net_device *dev, int length)
-{
-#ifdef CONFIG_NET_FASTROUTE
- struct ethhdr *eth;
- struct iphdr *iph;
- unsigned int hash;
- struct rtable *rt;
- struct net_device *odev;
- struct gfar_private *priv = netdev_priv(dev);
- 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;
-}