#include <net/dn_route.h>
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,
- .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,
__neigh_parms_put(neigh->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();
- if (dn->flags & DN_NDFLAG_P3)
- neigh->ops = &dn_phase3_ops;
-
+ neigh->ops = &dn_neigh_ops;
neigh->nud_state = NUD_NOARP;
neigh->output = neigh->ops->connected_output;
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);
}
-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 dn_route *rt = (struct dn_route *)dst;
- struct neighbour *neigh = rt->n;
struct net_device *dev = neigh->dev;
char mac_addr[ETH_ALEN];
unsigned int seq;
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)
{
struct net_device *dev = neigh->dev;
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)
{
struct net_device *dev = neigh->dev;
}
/*
- * 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.
*/
static int dn_phase3_output(struct neighbour *neigh, struct sk_buff *skb)
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
* function, so we don't get any advantage from it. This function