/*
* IPv6 output functions
- * Linux INET6 implementation
+ * Linux INET6 implementation
*
* Authors:
- * Pedro Roque <roque@di.fc.ul.pt>
+ * Pedro Roque <roque@di.fc.ul.pt>
*
* $Id: ip6_output.c,v 1.34 2002/02/01 22:01:04 davem Exp $
*
static inline int ip6_output_finish(struct sk_buff *skb)
{
-
struct dst_entry *dst = skb->dst;
- struct hh_cache *hh = dst->hh;
-
- if (hh) {
- int hh_alen;
-
- read_lock_bh(&hh->hh_lock);
- hh_alen = HH_DATA_ALIGN(hh->hh_len);
- memcpy(skb->data - hh_alen, hh->hh_data, hh_alen);
- read_unlock_bh(&hh->hh_lock);
- skb_push(skb, hh->hh_len);
- return hh->hh_output(skb);
- } else if (dst->neighbour)
+
+ if (dst->hh)
+ return neigh_hh_output(dst->hh, skb);
+ else if (dst->neighbour)
return dst->neighbour->output(skb);
IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES);
struct dst_entry *dst = skb->dst;
struct ipv6hdr *hdr = skb->nh.ipv6h;
struct inet6_skb_parm *opt = IP6CB(skb);
-
+
if (ipv6_devconf.forwarding == 0)
goto error;
hdr = skb->nh.ipv6h;
/* Mangling hops number delayed to point after skb COW */
-
+
hdr->hop_limit--;
IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_OUTFORWDATAGRAMS);
skb_shinfo(skb)->frag_list = NULL;
/* BUILD HEADER */
+ *prevhdr = NEXTHDR_FRAGMENT;
tmp_hdr = kmemdup(skb->nh.raw, hlen, GFP_ATOMIC);
if (!tmp_hdr) {
IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_FRAGFAILS);
return -ENOMEM;
}
- *prevhdr = NEXTHDR_FRAGMENT;
__skb_pull(skb, hlen);
fh = (struct frag_hdr*)__skb_push(skb, sizeof(struct frag_hdr));
skb->nh.raw = __skb_push(skb, hlen);
frag->nh.ipv6h->payload_len = htons(frag->len - sizeof(struct ipv6hdr));
ip6_copy_metadata(frag, skb);
}
-
+
err = output(skb);
if(!err)
IP6_INC_STATS(ip6_dst_idev(&rt->u.dst), IPSTATS_MIB_FRAGCREATES);
fail:
IP6_INC_STATS(ip6_dst_idev(skb->dst),
IPSTATS_MIB_FRAGFAILS);
- kfree_skb(skb);
+ kfree_skb(skb);
return err;
}
struct frag_hdr fhdr;
/* specify the length of each IP datagram fragment*/
- skb_shinfo(skb)->gso_size = mtu - fragheaderlen -
+ skb_shinfo(skb)->gso_size = mtu - fragheaderlen -
sizeof(struct frag_hdr);
skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
ipv6_select_ident(skb, &fhdr);
* fragment alignment (= 8-15 octects, in total).
*
* Note that we may need to "move" the data from the tail of
- * of the buffer to the new fragment when we split
+ * of the buffer to the new fragment when we split
* the message.
*
- * FIXME: It may be fragmented into multiple chunks
+ * FIXME: It may be fragmented into multiple chunks
* at once if non-fragmentable extension headers
* are too large.
- * --yoshfuji
+ * --yoshfuji
*/
inet->cork.length += length;
/*
* We just reserve space for fragment header.
- * Note: this may be overallocation if the message
+ * Note: this may be overallocation if the message
* (without MSG_MORE) fits into the MTU.
*/
alloclen += sizeof(struct frag_hdr);
ipv6_push_nfrag_opts(skb, opt, &proto, &final_dst);
skb->nh.ipv6h = hdr = (struct ipv6hdr*) skb_push(skb, sizeof(struct ipv6hdr));
-
+
*(__be32*)hdr = fl->fl6_flowlabel |
htonl(0x60000000 | ((int)np->cork.tclass << 20));