|
@@ -49,41 +49,17 @@
|
|
|
#include <net/dn_route.h>
|
|
#include <net/dn_route.h>
|
|
|
|
|
|
|
|
static int dn_neigh_construct(struct neighbour *);
|
|
static int dn_neigh_construct(struct neighbour *);
|
|
|
-static void dn_long_error_report(struct neighbour *, struct sk_buff *);
|
|
|
|
|
-static void dn_short_error_report(struct neighbour *, struct sk_buff *);
|
|
|
|
|
-static int dn_long_output(struct neighbour *, struct sk_buff *);
|
|
|
|
|
-static int dn_short_output(struct neighbour *, struct sk_buff *);
|
|
|
|
|
-static int dn_phase3_output(struct neighbour *, struct sk_buff *);
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-/*
|
|
|
|
|
- * For talking to broadcast devices: Ethernet & PPP
|
|
|
|
|
- */
|
|
|
|
|
-static const struct neigh_ops dn_long_ops = {
|
|
|
|
|
- .family = AF_DECnet,
|
|
|
|
|
- .error_report = dn_long_error_report,
|
|
|
|
|
- .output = dn_long_output,
|
|
|
|
|
- .connected_output = dn_long_output,
|
|
|
|
|
-};
|
|
|
|
|
|
|
+static void dn_neigh_error_report(struct neighbour *, struct sk_buff *);
|
|
|
|
|
+static int dn_neigh_output(struct neighbour *neigh, struct sk_buff *skb);
|
|
|
|
|
|
|
|
/*
|
|
/*
|
|
|
- * For talking to pointopoint and multidrop devices: DDCMP and X.25
|
|
|
|
|
|
|
+ * Operations for adding the link layer header.
|
|
|
*/
|
|
*/
|
|
|
-static const struct neigh_ops dn_short_ops = {
|
|
|
|
|
|
|
+static const struct neigh_ops dn_neigh_ops = {
|
|
|
.family = AF_DECnet,
|
|
.family = AF_DECnet,
|
|
|
- .error_report = dn_short_error_report,
|
|
|
|
|
- .output = dn_short_output,
|
|
|
|
|
- .connected_output = dn_short_output,
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
-/*
|
|
|
|
|
- * For talking to DECnet phase III nodes
|
|
|
|
|
- */
|
|
|
|
|
-static const struct neigh_ops dn_phase3_ops = {
|
|
|
|
|
- .family = AF_DECnet,
|
|
|
|
|
- .error_report = dn_short_error_report, /* Can use short version here */
|
|
|
|
|
- .output = dn_phase3_output,
|
|
|
|
|
- .connected_output = dn_phase3_output,
|
|
|
|
|
|
|
+ .error_report = dn_neigh_error_report,
|
|
|
|
|
+ .output = dn_neigh_output,
|
|
|
|
|
+ .connected_output = dn_neigh_output,
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
static u32 dn_neigh_hash(const void *pkey,
|
|
static u32 dn_neigh_hash(const void *pkey,
|
|
@@ -153,16 +129,9 @@ static int dn_neigh_construct(struct neighbour *neigh)
|
|
|
|
|
|
|
|
__neigh_parms_put(neigh->parms);
|
|
__neigh_parms_put(neigh->parms);
|
|
|
neigh->parms = neigh_parms_clone(parms);
|
|
neigh->parms = neigh_parms_clone(parms);
|
|
|
-
|
|
|
|
|
- if (dn_db->use_long)
|
|
|
|
|
- neigh->ops = &dn_long_ops;
|
|
|
|
|
- else
|
|
|
|
|
- neigh->ops = &dn_short_ops;
|
|
|
|
|
rcu_read_unlock();
|
|
rcu_read_unlock();
|
|
|
|
|
|
|
|
- if (dn->flags & DN_NDFLAG_P3)
|
|
|
|
|
- neigh->ops = &dn_phase3_ops;
|
|
|
|
|
-
|
|
|
|
|
|
|
+ neigh->ops = &dn_neigh_ops;
|
|
|
neigh->nud_state = NUD_NOARP;
|
|
neigh->nud_state = NUD_NOARP;
|
|
|
neigh->output = neigh->ops->connected_output;
|
|
neigh->output = neigh->ops->connected_output;
|
|
|
|
|
|
|
@@ -194,24 +163,16 @@ static int dn_neigh_construct(struct neighbour *neigh)
|
|
|
return 0;
|
|
return 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-static void dn_long_error_report(struct neighbour *neigh, struct sk_buff *skb)
|
|
|
|
|
-{
|
|
|
|
|
- printk(KERN_DEBUG "dn_long_error_report: called\n");
|
|
|
|
|
- kfree_skb(skb);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-static void dn_short_error_report(struct neighbour *neigh, struct sk_buff *skb)
|
|
|
|
|
|
|
+static void dn_neigh_error_report(struct neighbour *neigh, struct sk_buff *skb)
|
|
|
{
|
|
{
|
|
|
- printk(KERN_DEBUG "dn_short_error_report: called\n");
|
|
|
|
|
|
|
+ printk(KERN_DEBUG "dn_neigh_error_report: called\n");
|
|
|
kfree_skb(skb);
|
|
kfree_skb(skb);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-static int dn_neigh_output_packet(struct sk_buff *skb)
|
|
|
|
|
|
|
+static int dn_neigh_output(struct neighbour *neigh, struct sk_buff *skb)
|
|
|
{
|
|
{
|
|
|
struct dst_entry *dst = skb_dst(skb);
|
|
struct dst_entry *dst = skb_dst(skb);
|
|
|
struct dn_route *rt = (struct dn_route *)dst;
|
|
struct dn_route *rt = (struct dn_route *)dst;
|
|
|
- struct neighbour *neigh = rt->n;
|
|
|
|
|
struct net_device *dev = neigh->dev;
|
|
struct net_device *dev = neigh->dev;
|
|
|
char mac_addr[ETH_ALEN];
|
|
char mac_addr[ETH_ALEN];
|
|
|
unsigned int seq;
|
|
unsigned int seq;
|
|
@@ -233,6 +194,18 @@ static int dn_neigh_output_packet(struct sk_buff *skb)
|
|
|
return err;
|
|
return err;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+static int dn_neigh_output_packet(struct sk_buff *skb)
|
|
|
|
|
+{
|
|
|
|
|
+ struct dst_entry *dst = skb_dst(skb);
|
|
|
|
|
+ struct dn_route *rt = (struct dn_route *)dst;
|
|
|
|
|
+ struct neighbour *neigh = rt->n;
|
|
|
|
|
+
|
|
|
|
|
+ return neigh->output(neigh, skb);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/*
|
|
|
|
|
+ * For talking to broadcast devices: Ethernet & PPP
|
|
|
|
|
+ */
|
|
|
static int dn_long_output(struct neighbour *neigh, struct sk_buff *skb)
|
|
static int dn_long_output(struct neighbour *neigh, struct sk_buff *skb)
|
|
|
{
|
|
{
|
|
|
struct net_device *dev = neigh->dev;
|
|
struct net_device *dev = neigh->dev;
|
|
@@ -276,6 +249,9 @@ static int dn_long_output(struct neighbour *neigh, struct sk_buff *skb)
|
|
|
neigh->dev, dn_neigh_output_packet);
|
|
neigh->dev, dn_neigh_output_packet);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+/*
|
|
|
|
|
+ * For talking to pointopoint and multidrop devices: DDCMP and X.25
|
|
|
|
|
+ */
|
|
|
static int dn_short_output(struct neighbour *neigh, struct sk_buff *skb)
|
|
static int dn_short_output(struct neighbour *neigh, struct sk_buff *skb)
|
|
|
{
|
|
{
|
|
|
struct net_device *dev = neigh->dev;
|
|
struct net_device *dev = neigh->dev;
|
|
@@ -313,7 +289,8 @@ static int dn_short_output(struct neighbour *neigh, struct sk_buff *skb)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
/*
|
|
|
- * Phase 3 output is the same is short output, execpt that
|
|
|
|
|
|
|
+ * For talking to DECnet phase III nodes
|
|
|
|
|
+ * Phase 3 output is the same as short output, execpt that
|
|
|
* it clears the area bits before transmission.
|
|
* it clears the area bits before transmission.
|
|
|
*/
|
|
*/
|
|
|
static int dn_phase3_output(struct neighbour *neigh, struct sk_buff *skb)
|
|
static 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)
|
|
|
neigh->dev, dn_neigh_output_packet);
|
|
neigh->dev, dn_neigh_output_packet);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+int dn_to_neigh_output(struct sk_buff *skb)
|
|
|
|
|
+{
|
|
|
|
|
+ struct dst_entry *dst = skb_dst(skb);
|
|
|
|
|
+ struct dn_route *rt = (struct dn_route *) dst;
|
|
|
|
|
+ struct neighbour *neigh = rt->n;
|
|
|
|
|
+ struct dn_neigh *dn = (struct dn_neigh *)neigh;
|
|
|
|
|
+ struct dn_dev *dn_db;
|
|
|
|
|
+ bool use_long;
|
|
|
|
|
+
|
|
|
|
|
+ rcu_read_lock();
|
|
|
|
|
+ dn_db = rcu_dereference(neigh->dev->dn_ptr);
|
|
|
|
|
+ if (dn_db == NULL) {
|
|
|
|
|
+ rcu_read_unlock();
|
|
|
|
|
+ return -EINVAL;
|
|
|
|
|
+ }
|
|
|
|
|
+ use_long = dn_db->use_long;
|
|
|
|
|
+ rcu_read_unlock();
|
|
|
|
|
+
|
|
|
|
|
+ if (dn->flags & DN_NDFLAG_P3)
|
|
|
|
|
+ return dn_phase3_output(neigh, skb);
|
|
|
|
|
+ if (use_long)
|
|
|
|
|
+ return dn_long_output(neigh, skb);
|
|
|
|
|
+ else
|
|
|
|
|
+ return dn_short_output(neigh, skb);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
/*
|
|
/*
|
|
|
* Unfortunately, the neighbour code uses the device in its hash
|
|
* Unfortunately, the neighbour code uses the device in its hash
|
|
|
* function, so we don't get any advantage from it. This function
|
|
* function, so we don't get any advantage from it. This function
|