Skip to content

Commit

Permalink
net: Add STP demux layer
Browse files Browse the repository at this point in the history
Add small STP demux layer for demuxing STP PDUs based on MAC address.
This is needed to run both GARP and STP in parallel (or even load the
modules) since both use LLC_SAP_BSPAN.

Signed-off-by: Patrick McHardy <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
kaber authored and davem330 committed Jul 6, 2008
1 parent ef28d1a commit a19800d
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 0 deletions.
14 changes: 14 additions & 0 deletions include/net/stp.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#ifndef _NET_STP_H
#define _NET_STP_H

struct stp_proto {
unsigned char group_address[ETH_ALEN];
void (*rcv)(const struct stp_proto *, struct sk_buff *,
struct net_device *);
void *data;
};

extern int stp_proto_register(const struct stp_proto *proto);
extern void stp_proto_unregister(const struct stp_proto *proto);

#endif /* _NET_STP_H */
3 changes: 3 additions & 0 deletions net/802/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
config STP
tristate
select LLC
1 change: 1 addition & 0 deletions net/802/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ obj-$(CONFIG_FDDI) += fddi.o
obj-$(CONFIG_HIPPI) += hippi.o
obj-$(CONFIG_IPX) += p8022.o psnap.o p8023.o
obj-$(CONFIG_ATALK) += p8022.o psnap.o
obj-$(CONFIG_STP) += stp.o
102 changes: 102 additions & 0 deletions net/802/stp.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
* STP SAP demux
*
* Copyright (c) 2008 Patrick McHardy <[email protected]>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*/
#include <linux/mutex.h>
#include <linux/skbuff.h>
#include <linux/etherdevice.h>
#include <linux/llc.h>
#include <net/llc.h>
#include <net/llc_pdu.h>
#include <net/stp.h>

/* 01:80:c2:00:00:20 - 01:80:c2:00:00:2F */
#define GARP_ADDR_MIN 0x20
#define GARP_ADDR_MAX 0x2F
#define GARP_ADDR_RANGE (GARP_ADDR_MAX - GARP_ADDR_MIN)

static const struct stp_proto *garp_protos[GARP_ADDR_RANGE + 1] __read_mostly;
static const struct stp_proto *stp_proto __read_mostly;

static struct llc_sap *sap __read_mostly;
static unsigned int sap_registered;
static DEFINE_MUTEX(stp_proto_mutex);

/* Called under rcu_read_lock from LLC */
static int stp_pdu_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt, struct net_device *orig_dev)
{
const struct ethhdr *eh = eth_hdr(skb);
const struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
const struct stp_proto *proto;

if (pdu->ssap != LLC_SAP_BSPAN ||
pdu->dsap != LLC_SAP_BSPAN ||
pdu->ctrl_1 != LLC_PDU_TYPE_U)
goto err;

if (eh->h_dest[5] >= GARP_ADDR_MIN && eh->h_dest[5] <= GARP_ADDR_MAX) {
proto = rcu_dereference(garp_protos[eh->h_dest[5] -
GARP_ADDR_MIN]);
if (proto &&
compare_ether_addr(eh->h_dest, proto->group_address))
goto err;
} else
proto = rcu_dereference(stp_proto);

if (!proto)
goto err;

proto->rcv(proto, skb, dev);
return 0;

err:
kfree_skb(skb);
return 0;
}

int stp_proto_register(const struct stp_proto *proto)
{
int err = 0;

mutex_lock(&stp_proto_mutex);
if (sap_registered++ == 0) {
sap = llc_sap_open(LLC_SAP_BSPAN, stp_pdu_rcv);
if (!sap) {
err = -ENOMEM;
goto out;
}
}
if (is_zero_ether_addr(proto->group_address))
rcu_assign_pointer(stp_proto, proto);
else
rcu_assign_pointer(garp_protos[proto->group_address[5] -
GARP_ADDR_MIN], proto);
out:
mutex_unlock(&stp_proto_mutex);
return err;
}
EXPORT_SYMBOL_GPL(stp_proto_register);

void stp_proto_unregister(const struct stp_proto *proto)
{
mutex_lock(&stp_proto_mutex);
if (is_zero_ether_addr(proto->group_address))
rcu_assign_pointer(stp_proto, NULL);
else
rcu_assign_pointer(garp_protos[proto->group_address[5] -
GARP_ADDR_MIN], NULL);
synchronize_rcu();

if (--sap_registered == 0)
llc_sap_put(sap);
mutex_unlock(&stp_proto_mutex);
}
EXPORT_SYMBOL_GPL(stp_proto_unregister);

MODULE_LICENSE("GPL");
1 change: 1 addition & 0 deletions net/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ source "net/dccp/Kconfig"
source "net/sctp/Kconfig"
source "net/tipc/Kconfig"
source "net/atm/Kconfig"
source "net/802/Kconfig"
source "net/bridge/Kconfig"
source "net/8021q/Kconfig"
source "net/decnet/Kconfig"
Expand Down

0 comments on commit a19800d

Please sign in to comment.