diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2005-09-12 17:21:48 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2005-09-12 17:21:48 -0400 |
commit | 3f2aadd041a7a3e732d182c3770b3fa95a2300b2 (patch) | |
tree | be2917b8e811c91d95a2413bb31ee44e99dadb88 | |
parent | 6f74998e5c3b4610e6eba06babf16547369c512a (diff) |
[NETROM]: Fix rebuild header mess
For reason that probably nobody recalls NET/ROM does it's actual
packet transmission in nr_rebuild_header and even treats invocation of
it's hard_start_xmit method nr_xmit as a bug. Fix that by splitting
the job done by nr_rebuild_header into two halves. Along with that we
now also can get rid of the silly clone of the skb on transmit.
Signed-off-by: Ralf Baechle DL5RB <ralf@linux-mips.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/netrom/nr_dev.c | 44 |
1 files changed, 15 insertions, 29 deletions
diff --git a/net/netrom/nr_dev.c b/net/netrom/nr_dev.c index 263da4c26494..431a25384421 100644 --- a/net/netrom/nr_dev.c +++ b/net/netrom/nr_dev.c | |||
@@ -71,15 +71,10 @@ int nr_rx_ip(struct sk_buff *skb, struct net_device *dev) | |||
71 | 71 | ||
72 | static int nr_rebuild_header(struct sk_buff *skb) | 72 | static int nr_rebuild_header(struct sk_buff *skb) |
73 | { | 73 | { |
74 | struct net_device *dev = skb->dev; | ||
75 | struct net_device_stats *stats = netdev_priv(dev); | ||
76 | struct sk_buff *skbn; | ||
77 | unsigned char *bp = skb->data; | 74 | unsigned char *bp = skb->data; |
78 | int len; | ||
79 | 75 | ||
80 | if (arp_find(bp + 7, skb)) { | 76 | if (arp_find(bp + 7, skb)) |
81 | return 1; | 77 | return 1; |
82 | } | ||
83 | 78 | ||
84 | bp[6] &= ~AX25_CBIT; | 79 | bp[6] &= ~AX25_CBIT; |
85 | bp[6] &= ~AX25_EBIT; | 80 | bp[6] &= ~AX25_EBIT; |
@@ -90,27 +85,7 @@ static int nr_rebuild_header(struct sk_buff *skb) | |||
90 | bp[6] |= AX25_EBIT; | 85 | bp[6] |= AX25_EBIT; |
91 | bp[6] |= AX25_SSSID_SPARE; | 86 | bp[6] |= AX25_SSSID_SPARE; |
92 | 87 | ||
93 | if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) { | 88 | return 0; |
94 | kfree_skb(skb); | ||
95 | return 1; | ||
96 | } | ||
97 | |||
98 | if (skb->sk != NULL) | ||
99 | skb_set_owner_w(skbn, skb->sk); | ||
100 | |||
101 | kfree_skb(skb); | ||
102 | |||
103 | len = skbn->len; | ||
104 | |||
105 | if (!nr_route_frame(skbn, NULL)) { | ||
106 | kfree_skb(skbn); | ||
107 | stats->tx_errors++; | ||
108 | } | ||
109 | |||
110 | stats->tx_packets++; | ||
111 | stats->tx_bytes += len; | ||
112 | |||
113 | return 1; | ||
114 | } | 89 | } |
115 | 90 | ||
116 | #else | 91 | #else |
@@ -186,8 +161,19 @@ static int nr_close(struct net_device *dev) | |||
186 | static int nr_xmit(struct sk_buff *skb, struct net_device *dev) | 161 | static int nr_xmit(struct sk_buff *skb, struct net_device *dev) |
187 | { | 162 | { |
188 | struct net_device_stats *stats = netdev_priv(dev); | 163 | struct net_device_stats *stats = netdev_priv(dev); |
189 | dev_kfree_skb(skb); | 164 | unsigned int len; |
190 | stats->tx_errors++; | 165 | |
166 | len = skb->len; | ||
167 | |||
168 | if (!nr_route_frame(skb, NULL)) { | ||
169 | kfree_skb(skb); | ||
170 | stats->tx_errors++; | ||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | stats->tx_packets++; | ||
175 | stats->tx_bytes += len; | ||
176 | |||
191 | return 0; | 177 | return 0; |
192 | } | 178 | } |
193 | 179 | ||