aboutsummaryrefslogtreecommitdiffstats
path: root/net/decnet
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2015-03-04 11:16:43 -0500
committerDavid S. Miller <davem@davemloft.net>2015-03-06 14:54:22 -0500
commitaaa4e70404c7b38a8792dc69af54afd7218b2ec0 (patch)
tree97e298abfa74712540b528fb7d7436c10175b1f3 /net/decnet
parent616f45416ca0d726d6d3421a296ebc6e2bb82cde (diff)
DECnet: Only use neigh_ops for adding the link layer header
Other users users of the neighbour table use neigh->output as the method to decided when and which link-layer header to place on a packet. DECnet has been using neigh->output to decide which DECnet headers to place on a packet depending which neighbour the packet is destined for. The DECnet usage isn't totally wrong but it can run into problems if the neighbour output function is run for a second time as the teql driver and the bridge netfilter code can do. Therefore to avoid pathologic problems later down the line and make the neighbour code easier to understand by refactoring the decnet output code to only use a neighbour method to add a link layer header to a packet. This is done by moving the neigbhour operations lookup from dn_to_neigh_output to dn_neigh_output_packet. Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/decnet')
-rw-r--r--net/decnet/dn_neigh.c105
-rw-r--r--net/decnet/dn_route.c9
2 files changed, 54 insertions, 60 deletions
diff --git a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c
index ee7d1cef0027..be1f08cdad29 100644
--- a/net/decnet/dn_neigh.c
+++ b/net/decnet/dn_neigh.c
@@ -49,41 +49,17 @@
49#include <net/dn_route.h> 49#include <net/dn_route.h>
50 50
51static int dn_neigh_construct(struct neighbour *); 51static int dn_neigh_construct(struct neighbour *);
52static void dn_long_error_report(struct neighbour *, struct sk_buff *); 52static void dn_neigh_error_report(struct neighbour *, struct sk_buff *);
53static void dn_short_error_report(struct neighbour *, struct sk_buff *); 53static int dn_neigh_output(struct neighbour *neigh, struct sk_buff *skb);
54static int dn_long_output(struct neighbour *, struct sk_buff *);
55static int dn_short_output(struct neighbour *, struct sk_buff *);
56static int dn_phase3_output(struct neighbour *, struct sk_buff *);
57
58
59/*
60 * For talking to broadcast devices: Ethernet & PPP
61 */
62static const struct neigh_ops dn_long_ops = {
63 .family = AF_DECnet,
64 .error_report = dn_long_error_report,
65 .output = dn_long_output,
66 .connected_output = dn_long_output,
67};
68 54
69/* 55/*
70 * For talking to pointopoint and multidrop devices: DDCMP and X.25 56 * Operations for adding the link layer header.
71 */ 57 */
72static const struct neigh_ops dn_short_ops = { 58static const struct neigh_ops dn_neigh_ops = {
73 .family = AF_DECnet, 59 .family = AF_DECnet,
74 .error_report = dn_short_error_report, 60 .error_report = dn_neigh_error_report,
75 .output = dn_short_output, 61 .output = dn_neigh_output,
76 .connected_output = dn_short_output, 62 .connected_output = dn_neigh_output,
77};
78
79/*
80 * For talking to DECnet phase III nodes
81 */
82static const struct neigh_ops dn_phase3_ops = {
83 .family = AF_DECnet,
84 .error_report = dn_short_error_report, /* Can use short version here */
85 .output = dn_phase3_output,
86 .connected_output = dn_phase3_output,
87}; 63};
88 64
89static u32 dn_neigh_hash(const void *pkey, 65static u32 dn_neigh_hash(const void *pkey,
@@ -153,16 +129,9 @@ static int dn_neigh_construct(struct neighbour *neigh)
153 129
154 __neigh_parms_put(neigh->parms); 130 __neigh_parms_put(neigh->parms);
155 neigh->parms = neigh_parms_clone(parms); 131 neigh->parms = neigh_parms_clone(parms);
156
157 if (dn_db->use_long)
158 neigh->ops = &dn_long_ops;
159 else
160 neigh->ops = &dn_short_ops;
161 rcu_read_unlock(); 132 rcu_read_unlock();
162 133
163 if (dn->flags & DN_NDFLAG_P3) 134 neigh->ops = &dn_neigh_ops;
164 neigh->ops = &dn_phase3_ops;
165
166 neigh->nud_state = NUD_NOARP; 135 neigh->nud_state = NUD_NOARP;
167 neigh->output = neigh->ops->connected_output; 136 neigh->output = neigh->ops->connected_output;
168 137
@@ -194,24 +163,16 @@ static int dn_neigh_construct(struct neighbour *neigh)
194 return 0; 163 return 0;
195} 164}
196 165
197static void dn_long_error_report(struct neighbour *neigh, struct sk_buff *skb) 166static void dn_neigh_error_report(struct neighbour *neigh, struct sk_buff *skb)
198{
199 printk(KERN_DEBUG "dn_long_error_report: called\n");
200 kfree_skb(skb);
201}
202
203
204static void dn_short_error_report(struct neighbour *neigh, struct sk_buff *skb)
205{ 167{
206 printk(KERN_DEBUG "dn_short_error_report: called\n"); 168 printk(KERN_DEBUG "dn_neigh_error_report: called\n");
207 kfree_skb(skb); 169 kfree_skb(skb);
208} 170}
209 171
210static int dn_neigh_output_packet(struct sk_buff *skb) 172static int dn_neigh_output(struct neighbour *neigh, struct sk_buff *skb)
211{ 173{
212 struct dst_entry *dst = skb_dst(skb); 174 struct dst_entry *dst = skb_dst(skb);
213 struct dn_route *rt = (struct dn_route *)dst; 175 struct dn_route *rt = (struct dn_route *)dst;
214 struct neighbour *neigh = rt->n;
215 struct net_device *dev = neigh->dev; 176 struct net_device *dev = neigh->dev;
216 char mac_addr[ETH_ALEN]; 177 char mac_addr[ETH_ALEN];
217 unsigned int seq; 178 unsigned int seq;
@@ -233,6 +194,18 @@ static int dn_neigh_output_packet(struct sk_buff *skb)
233 return err; 194 return err;
234} 195}
235 196
197static int dn_neigh_output_packet(struct sk_buff *skb)
198{
199 struct dst_entry *dst = skb_dst(skb);
200 struct dn_route *rt = (struct dn_route *)dst;
201 struct neighbour *neigh = rt->n;
202
203 return neigh->output(neigh, skb);
204}
205
206/*
207 * For talking to broadcast devices: Ethernet & PPP
208 */
236static int dn_long_output(struct neighbour *neigh, struct sk_buff *skb) 209static int dn_long_output(struct neighbour *neigh, struct sk_buff *skb)
237{ 210{
238 struct net_device *dev = neigh->dev; 211 struct net_device *dev = neigh->dev;
@@ -276,6 +249,9 @@ static int dn_long_output(struct neighbour *neigh, struct sk_buff *skb)
276 neigh->dev, dn_neigh_output_packet); 249 neigh->dev, dn_neigh_output_packet);
277} 250}
278 251
252/*
253 * For talking to pointopoint and multidrop devices: DDCMP and X.25
254 */
279static int dn_short_output(struct neighbour *neigh, struct sk_buff *skb) 255static int dn_short_output(struct neighbour *neigh, struct sk_buff *skb)
280{ 256{
281 struct net_device *dev = neigh->dev; 257 struct net_device *dev = neigh->dev;
@@ -313,7 +289,8 @@ static int dn_short_output(struct neighbour *neigh, struct sk_buff *skb)
313} 289}
314 290
315/* 291/*
316 * Phase 3 output is the same is short output, execpt that 292 * For talking to DECnet phase III nodes
293 * Phase 3 output is the same as short output, execpt that
317 * it clears the area bits before transmission. 294 * it clears the area bits before transmission.
318 */ 295 */
319static int dn_phase3_output(struct neighbour *neigh, struct sk_buff *skb) 296static int dn_phase3_output(struct neighbour *neigh, struct sk_buff *skb)
@@ -351,6 +328,32 @@ static int dn_phase3_output(struct neighbour *neigh, struct sk_buff *skb)
351 neigh->dev, dn_neigh_output_packet); 328 neigh->dev, dn_neigh_output_packet);
352} 329}
353 330
331int dn_to_neigh_output(struct sk_buff *skb)
332{
333 struct dst_entry *dst = skb_dst(skb);
334 struct dn_route *rt = (struct dn_route *) dst;
335 struct neighbour *neigh = rt->n;
336 struct dn_neigh *dn = (struct dn_neigh *)neigh;
337 struct dn_dev *dn_db;
338 bool use_long;
339
340 rcu_read_lock();
341 dn_db = rcu_dereference(neigh->dev->dn_ptr);
342 if (dn_db == NULL) {
343 rcu_read_unlock();
344 return -EINVAL;
345 }
346 use_long = dn_db->use_long;
347 rcu_read_unlock();
348
349 if (dn->flags & DN_NDFLAG_P3)
350 return dn_phase3_output(neigh, skb);
351 if (use_long)
352 return dn_long_output(neigh, skb);
353 else
354 return dn_short_output(neigh, skb);
355}
356
354/* 357/*
355 * Unfortunately, the neighbour code uses the device in its hash 358 * Unfortunately, the neighbour code uses the device in its hash
356 * function, so we don't get any advantage from it. This function 359 * function, so we don't get any advantage from it. This function
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index 3b81092771f8..771815575dbd 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -743,15 +743,6 @@ out:
743 return NET_RX_DROP; 743 return NET_RX_DROP;
744} 744}
745 745
746static int dn_to_neigh_output(struct sk_buff *skb)
747{
748 struct dst_entry *dst = skb_dst(skb);
749 struct dn_route *rt = (struct dn_route *) dst;
750 struct neighbour *n = rt->n;
751
752 return n->output(n, skb);
753}
754
755static int dn_output(struct sock *sk, struct sk_buff *skb) 746static int dn_output(struct sock *sk, struct sk_buff *skb)
756{ 747{
757 struct dst_entry *dst = skb_dst(skb); 748 struct dst_entry *dst = skb_dst(skb);