Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 237510
b: refs/heads/master
c: 1c32c5a
h: refs/heads/master
v: v3
  • Loading branch information
Herbert Xu authored and David S. Miller committed Mar 1, 2011
1 parent 02f0213 commit 0b5bad9
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 15 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 1470ddf7f8cecf776921e5ccee72e3d2b3d60cbc
refs/heads/master: 1c32c5ad6fac8cee1a77449f5abf211e911ff830
16 changes: 16 additions & 0 deletions trunk/include/net/ip.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,24 @@ extern int ip_append_data(struct sock *sk,
extern int ip_generic_getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb);
extern ssize_t ip_append_page(struct sock *sk, struct page *page,
int offset, size_t size, int flags);
extern struct sk_buff *__ip_make_skb(struct sock *sk,
struct sk_buff_head *queue,
struct inet_cork *cork);
extern int ip_send_skb(struct sk_buff *skb);
extern int ip_push_pending_frames(struct sock *sk);
extern void ip_flush_pending_frames(struct sock *sk);
extern struct sk_buff *ip_make_skb(struct sock *sk,
int getfrag(void *from, char *to, int offset, int len,
int odd, struct sk_buff *skb),
void *from, int length, int transhdrlen,
struct ipcm_cookie *ipc,
struct rtable **rtp,
unsigned int flags);

static inline struct sk_buff *ip_finish_skb(struct sock *sk)
{
return __ip_make_skb(sk, &sk->sk_write_queue, &inet_sk(sk)->cork);
}

/* datagram.c */
extern int ip4_datagram_connect(struct sock *sk,
Expand Down
65 changes: 51 additions & 14 deletions trunk/net/ipv4/ip_output.c
Original file line number Diff line number Diff line change
Expand Up @@ -1267,9 +1267,9 @@ static void ip_cork_release(struct inet_cork *cork)
* Combined all pending IP fragments on the socket as one IP datagram
* and push them out.
*/
static int __ip_push_pending_frames(struct sock *sk,
struct sk_buff_head *queue,
struct inet_cork *cork)
struct sk_buff *__ip_make_skb(struct sock *sk,
struct sk_buff_head *queue,
struct inet_cork *cork)
{
struct sk_buff *skb, *tmp_skb;
struct sk_buff **tail_skb;
Expand All @@ -1280,7 +1280,6 @@ static int __ip_push_pending_frames(struct sock *sk,
struct iphdr *iph;
__be16 df = 0;
__u8 ttl;
int err = 0;

if ((skb = __skb_dequeue(queue)) == NULL)
goto out;
Expand Down Expand Up @@ -1351,28 +1350,37 @@ static int __ip_push_pending_frames(struct sock *sk,
icmp_out_count(net, ((struct icmphdr *)
skb_transport_header(skb))->type);

/* Netfilter gets whole the not fragmented skb. */
ip_cork_release(cork);
out:
return skb;
}

int ip_send_skb(struct sk_buff *skb)
{
struct net *net = sock_net(skb->sk);
int err;

err = ip_local_out(skb);
if (err) {
if (err > 0)
err = net_xmit_errno(err);
if (err)
goto error;
IP_INC_STATS(net, IPSTATS_MIB_OUTDISCARDS);
}

out:
ip_cork_release(cork);
return err;

error:
IP_INC_STATS(net, IPSTATS_MIB_OUTDISCARDS);
goto out;
}

int ip_push_pending_frames(struct sock *sk)
{
return __ip_push_pending_frames(sk, &sk->sk_write_queue,
&inet_sk(sk)->cork);
struct sk_buff *skb;

skb = ip_finish_skb(sk);
if (!skb)
return 0;

/* Netfilter gets whole the not fragmented skb. */
return ip_send_skb(skb);
}

/*
Expand All @@ -1395,6 +1403,35 @@ void ip_flush_pending_frames(struct sock *sk)
__ip_flush_pending_frames(sk, &sk->sk_write_queue, &inet_sk(sk)->cork);
}

struct sk_buff *ip_make_skb(struct sock *sk,
int getfrag(void *from, char *to, int offset,
int len, int odd, struct sk_buff *skb),
void *from, int length, int transhdrlen,
struct ipcm_cookie *ipc, struct rtable **rtp,
unsigned int flags)
{
struct inet_cork cork = {};
struct sk_buff_head queue;
int err;

if (flags & MSG_PROBE)
return NULL;

__skb_queue_head_init(&queue);

err = ip_setup_cork(sk, &cork, ipc, rtp);
if (err)
return ERR_PTR(err);

err = __ip_append_data(sk, &queue, &cork, getfrag,
from, length, transhdrlen, flags);
if (err) {
__ip_flush_pending_frames(sk, &queue, &cork);
return ERR_PTR(err);
}

return __ip_make_skb(sk, &queue, &cork);
}

/*
* Fetch data from kernel space and fill in checksum if needed.
Expand Down

0 comments on commit 0b5bad9

Please sign in to comment.