Hi All,

In these days I adapted the last patch for br2684 kernel module.

For some ISP it is necesary this implementation.

This is my case in Spain with Telefonica ISP and static IP.

Adapted support for kernel 2.6.24 

Implemented:
-------------------------------------------------------------
Kernel
  - target/linux/generic-2.6/patches-2.6.24/601-br2684-routed-support.patch
  -> linux-2.6.24.2/include/linux/atmbr2684.h
  -> linux-2.6.24.2/net/atm/br2684.c

Package
- package/br2684ctl/patches/101-routed_support.patch
  -> br2684ctl-20040226.orig/br2684ctl.c
Scripts
  - package/br2684ctl/files/br2684ctl
  -------------------------------------------------------------
  
This changes the br2684 module of kernel 2.6.24, br2864ctl package and
br2684ctl script. With this changes it is posible 

Tested for 7 days with Linksys AG241v2-EU.
  
Configuracion /etc/config/network
-------------------------------------------------------------
config atm-bridge
        option 'unit'    '0'
        option 'vpi'     '8'
        option 'vci'     '32'
        option 'encaps'  'llc'
        option 'payload' 'routed'

config 'interface' 'wan'
        option 'ifname' 'nas0'
        option 'proto' 'static'
        option 'ipaddr' 'your ipaddr'
        option 'netmask' 'your netmask'
        option 'dns' 'your dns'
        option 'gateway' 'your gateway'
-------------------------------------------------------------

cat /proc/net/atm/br2684  
-------------------------------------------------------------
  

[EMAIL PROTECTED]:/tmp# cat /proc/net/atm/br2684
dev nas0: num=1, mac=00:00:00:00:00:00 (auto)
  vcc 0.8.32: encaps=LLC payload=routed, failed copies 0/0
-------------------------------------------------------------Signed-off-by: 
Juan I. Gonzalez <juan.i.gonzalez at subdown dot net>


  


--
PRIVACIDAD:
Este mensaje se dirige exclusivamente a su destinatario y puede contener
información privilegiada o CONFIDENCIAL. Si no es vd. el destinatario
indicado, queda notificado de que la utilización, divulgación y/o copia sin
autorización está prohibida en virtud de la legislación vigente. Si ha
recibido este mensaje por error, le rogamos que nos lo comunique
inmediatamente por esta misma vía y proceda a su destrucción.

PRIVACITY:
This message is intended exclusively for its addressee and may contain
information that is CONFIDENTIAL and protected by professional privilege. If
you are not the intended recipient you are hereby notified that any
dissemination, copy or disclosure of this communication is strictly
prohibited by law. If this message has been received in error, please
immediately notify us via e-mail and delete it.

Powered by Subdown System Network
Index: target/linux/generic-2.6/patches-2.6.24/601-br2684-routed-support.patch
===================================================================
--- target/linux/generic-2.6/patches-2.6.24/601-br2684-routed-support.patch	(revision 0)
+++ target/linux/generic-2.6/patches-2.6.24/601-br2684-routed-support.patch	(revision 0)
@@ -0,0 +1,730 @@
+diff -Nur linux-2.6.24.2/include/linux/atmbr2684.h linux-2.6.24.2-copy/include/linux/atmbr2684.h
+--- linux-2.6.24.2/include/linux/atmbr2684.h	2008-02-11 05:51:11.000000000 +0000
++++ linux-2.6.24.2-copy/include/linux/atmbr2684.h	2008-03-27 01:08:42.000000000 +0000
+@@ -14,6 +14,9 @@
+ #define BR2684_MEDIA_FDDI	(3)
+ #define BR2684_MEDIA_802_6	(4)	/* 802.6 */
+ 
++					/* used only at device creation:  */
++#define BR2684_FLAG_ROUTED	(1<<16)	/* payload is routed, not bridged */
++
+ /*
+  * Is there FCS inbound on this VC?  This currently isn't supported.
+  */
+@@ -36,15 +39,22 @@
+ #define BR2684_ENCAPS_AUTODETECT (2)	/* Unsuported */
+ 
+ /*
++ * Is this VC bridged or routed?
++ */
++
++#define BR2684_PAYLOAD_ROUTED   (0)
++#define BR2684_PAYLOAD_BRIDGED  (1)
++
++/*
+  * This is for the ATM_NEWBACKENDIF call - these are like socket families:
+  * the first element of the structure is the backend number and the rest
+  * is per-backend specific
+  */
+ struct atm_newif_br2684 {
+-	atm_backend_t	backend_num;	/* ATM_BACKEND_BR2684 */
+-	int		media;		/* BR2684_MEDIA_* */
+-	char		ifname[IFNAMSIZ];
+-	int		mtu;
++	atm_backend_t backend_num;	/* ATM_BACKEND_BR2684 */
++	int media;		/* BR2684_MEDIA_*, flags in upper bits */
++	char ifname[IFNAMSIZ];
++	int mtu;
+ };
+ 
+ /*
+@@ -55,10 +65,10 @@
+ #define BR2684_FIND_BYNUM	(1)
+ #define BR2684_FIND_BYIFNAME	(2)
+ struct br2684_if_spec {
+-	int method;			/* BR2684_FIND_* */
++	int method;		/* BR2684_FIND_* */
+ 	union {
+-		char		ifname[IFNAMSIZ];
+-		int		devnum;
++		char ifname[IFNAMSIZ];
++		int devnum;
+ 	} spec;
+ };
+ 
+@@ -68,16 +78,16 @@
+  * is per-backend specific
+  */
+ struct atm_backend_br2684 {
+-	atm_backend_t	backend_num;	/* ATM_BACKEND_BR2684 */
++	atm_backend_t backend_num;	/* ATM_BACKEND_BR2684 */
+ 	struct br2684_if_spec ifspec;
+-	int	fcs_in;		/* BR2684_FCSIN_* */
+-	int	fcs_out;	/* BR2684_FCSOUT_* */
+-	int	fcs_auto;	/* 1: fcs_{in,out} disabled if no FCS rx'ed */
+-	int	encaps;		/* BR2684_ENCAPS_* */
+-	int	has_vpiid;	/* 1: use vpn_id - Unsupported */
+-	__u8	vpn_id[7];
+-	int	send_padding;	/* unsupported */
+-	int	min_size;	/* we will pad smaller packets than this */
++	int fcs_in;		/* BR2684_FCSIN_* */
++	int fcs_out;		/* BR2684_FCSOUT_* */
++	int fcs_auto;		/* 1: fcs_{in,out} disabled if no FCS rx'ed */
++	int encaps;		/* BR2684_ENCAPS_* */
++	int has_vpiid;		/* 1: use vpn_id - Unsupported */
++	__u8 vpn_id[7];
++	int send_padding;	/* unsupported */
++	int min_size;		/* we will pad smaller packets than this */
+ };
+ 
+ /*
+@@ -86,8 +96,8 @@
+  * efficient per-if in/out filters, this support will be removed
+  */
+ struct br2684_filter {
+-	__be32	prefix;		/* network byte order */
+-	__be32	netmask;	/* 0 = disable filter */
++	__be32 prefix;		/* network byte order */
++	__be32 netmask;		/* 0 = disable filter */
+ };
+ 
+ struct br2684_filter_set {
+@@ -95,7 +105,13 @@
+ 	struct br2684_filter filter;
+ };
+ 
++enum br2684_payload {
++	p_routed = BR2684_PAYLOAD_ROUTED,
++	p_bridged = BR2684_PAYLOAD_BRIDGED,
++};
++
+ #define BR2684_SETFILT	_IOW( 'a', ATMIOC_BACKEND + 0, \
+ 				struct br2684_filter_set)
+ 
+ #endif /* _LINUX_ATMBR2684_H */
++
+diff -Nur linux-2.6.24.2/net/atm/br2684.c linux-2.6.24.2-copy/net/atm/br2684.c
+--- linux-2.6.24.2/net/atm/br2684.c	2008-02-11 05:51:11.000000000 +0000
++++ linux-2.6.24.2-copy/net/atm/br2684.c	2008-03-27 03:24:17.000000000 +0000
+@@ -1,8 +1,10 @@
+ /*
+-Experimental ethernet netdevice using ATM AAL5 as underlying carrier
+-(RFC1483 obsoleted by RFC2684) for Linux 2.4
+-Author: Marcell GAL, 2000, XDSL Ltd, Hungary
+-*/
++ * Ethernet netdevice using ATM AAL5 as underlying carrier
++ * (RFC1483 obsoleted by RFC2684) for Linux
++ *
++ * Authors: Marcell GAL, 2000, XDSL Ltd, Hungary
++ *          Eric Kinzie, 2006-2007, US Naval Research Laboratory
++ */
+ 
+ #include <linux/module.h>
+ #include <linux/init.h>
+@@ -39,21 +41,35 @@
+ #define skb_debug(skb)	do {} while (0)
+ #endif
+ 
++#define BR2684_ETHERTYPE_LEN	2
++#define BR2684_PAD_LEN		2
++
++#define LLC		0xaa, 0xaa, 0x03
++#define SNAP_BRIDGED	0x00, 0x80, 0xc2
++#define SNAP_ROUTED	0x00, 0x00, 0x00
++#define PID_ETHERNET	0x00, 0x07
++#define ETHERTYPE_IPV4	0x08, 0x00
++#define ETHERTYPE_IPV6	0x86, 0xdd
++#define PAD_BRIDGED	0x00, 0x00
++
++static unsigned char ethertype_ipv4[] = { ETHERTYPE_IPV4 };
++static unsigned char ethertype_ipv6[] = { ETHERTYPE_IPV6 };
+ static unsigned char llc_oui_pid_pad[] =
+-    { 0xAA, 0xAA, 0x03, 0x00, 0x80, 0xC2, 0x00, 0x07, 0x00, 0x00 };
+-#define PADLEN	(2)
++			{ LLC, SNAP_BRIDGED, PID_ETHERNET, PAD_BRIDGED };
++static unsigned char llc_oui_ipv4[] = { LLC, SNAP_ROUTED, ETHERTYPE_IPV4 };
++static unsigned char llc_oui_ipv6[] = { LLC, SNAP_ROUTED, ETHERTYPE_IPV6 };
+ 
+ enum br2684_encaps {
+-	e_vc  = BR2684_ENCAPS_VC,
++	e_vc = BR2684_ENCAPS_VC,
+ 	e_llc = BR2684_ENCAPS_LLC,
+ };
+ 
+ struct br2684_vcc {
+-	struct atm_vcc  *atmvcc;
++	struct atm_vcc *atmvcc;
+ 	struct net_device *device;
+-	/* keep old push,pop functions for chaining */
+-	void (*old_push)(struct atm_vcc *vcc,struct sk_buff *skb);
+-	/* void (*old_pop)(struct atm_vcc *vcc,struct sk_buff *skb); */
++	/* keep old push, pop functions for chaining */
++	void (*old_push) (struct atm_vcc * vcc, struct sk_buff * skb);
++	/* void (*old_pop)(struct atm_vcc *vcc, struct sk_buff *skb); */
+ 	enum br2684_encaps encaps;
+ 	struct list_head brvccs;
+ #ifdef CONFIG_ATM_BR2684_IPFILTER
+@@ -66,9 +82,10 @@
+ 	struct net_device *net_dev;
+ 	struct list_head br2684_devs;
+ 	int number;
+-	struct list_head brvccs; /* one device <=> one vcc (before xmas) */
++	struct list_head brvccs;	/* one device <=> one vcc (before xmas) */
+ 	struct net_device_stats stats;
+ 	int mac_was_set;
++	enum br2684_payload payload;
+ };
+ 
+ /*
+@@ -84,7 +101,7 @@
+ 
+ static inline struct br2684_dev *BRPRIV(const struct net_device *net_dev)
+ {
+-	return (struct br2684_dev *) net_dev->priv;
++	return (struct br2684_dev *)net_dev->priv;
+ }
+ 
+ static inline struct net_device *list_entry_brdev(const struct list_head *le)
+@@ -94,7 +111,7 @@
+ 
+ static inline struct br2684_vcc *BR2684_VCC(const struct atm_vcc *atmvcc)
+ {
+-	return (struct br2684_vcc *) (atmvcc->user_back);
++	return (struct br2684_vcc *)(atmvcc->user_back);
+ }
+ 
+ static inline struct br2684_vcc *list_entry_brvcc(const struct list_head *le)
+@@ -132,10 +149,11 @@
+  * otherwise false
+  */
+ static int br2684_xmit_vcc(struct sk_buff *skb, struct br2684_dev *brdev,
+-	struct br2684_vcc *brvcc)
++			   struct br2684_vcc *brvcc)
+ {
+ 	struct atm_vcc *atmvcc;
+ 	int minheadroom = (brvcc->encaps == e_llc) ? 10 : 2;
++
+ 	if (skb_headroom(skb) < minheadroom) {
+ 		struct sk_buff *skb2 = skb_realloc_headroom(skb, minheadroom);
+ 		brvcc->copies_needed++;
+@@ -146,23 +164,48 @@
+ 		}
+ 		skb = skb2;
+ 	}
+-	skb_push(skb, minheadroom);
+-	if (brvcc->encaps == e_llc)
+-		skb_copy_to_linear_data(skb, llc_oui_pid_pad, 10);
+-	else
+-		memset(skb->data, 0, 2);
++
++	if (brvcc->encaps == e_llc) {
++		if (brdev->payload == p_bridged) {
++			skb_push(skb, sizeof(llc_oui_pid_pad));
++			skb_copy_to_linear_data(skb, llc_oui_pid_pad,
++						sizeof(llc_oui_pid_pad));
++		} else if (brdev->payload == p_routed) {
++			unsigned short prot = ntohs(skb->protocol);
++
++			skb_push(skb, sizeof(llc_oui_ipv4));
++			switch (prot) {
++			case ETH_P_IP:
++				skb_copy_to_linear_data(skb, llc_oui_ipv4,
++							sizeof(llc_oui_ipv4));
++				break;
++			case ETH_P_IPV6:
++				skb_copy_to_linear_data(skb, llc_oui_ipv6,
++							sizeof(llc_oui_ipv6));
++				break;
++			default:
++				dev_kfree_skb(skb);
++				return 0;
++			}
++		}
++	} else {
++		skb_push(skb, 2);
++		if (brdev->payload == p_bridged)
++			memset(skb->data, 0, 2);
++	}
+ 	skb_debug(skb);
+ 
+ 	ATM_SKB(skb)->vcc = atmvcc = brvcc->atmvcc;
+ 	pr_debug("atm_skb(%p)->vcc(%p)->dev(%p)\n", skb, atmvcc, atmvcc->dev);
+ 	if (!atm_may_send(atmvcc, skb->truesize)) {
+-		/* we free this here for now, because we cannot know in a higher
+-			layer whether the skb point it supplied wasn't freed yet.
+-			now, it always is.
+-		*/
++		/*
++		 * We free this here for now, because we cannot know in a higher
++		 * layer whether the skb pointer it supplied wasn't freed yet.
++		 * Now, it always is.
++		 */
+ 		dev_kfree_skb(skb);
+ 		return 0;
+-		}
++	}
+ 	atomic_add(skb->truesize, &sk_atm(atmvcc)->sk_wmem_alloc);
+ 	ATM_SKB(skb)->atm_options = atmvcc->atm_options;
+ 	brdev->stats.tx_packets++;
+@@ -172,10 +215,9 @@
+ }
+ 
+ static inline struct br2684_vcc *pick_outgoing_vcc(struct sk_buff *skb,
+-	struct br2684_dev *brdev)
++						   struct br2684_dev *brdev)
+ {
+-	return list_empty(&brdev->brvccs) ? NULL :
+-	    list_entry_brvcc(brdev->brvccs.next); /* 1 vcc/dev right now */
++	return list_empty(&brdev->brvccs) ? NULL : list_entry_brvcc(brdev->brvccs.next);	/* 1 vcc/dev right now */
+ }
+ 
+ static int br2684_start_xmit(struct sk_buff *skb, struct net_device *dev)
+@@ -199,11 +241,10 @@
+ 		/*
+ 		 * We should probably use netif_*_queue() here, but that
+ 		 * involves added complication.  We need to walk before
+-		 * we can run
++		 * we can run.
++		 *
++		 * Don't free here! this pointer might be no longer valid!
+ 		 */
+-		/* don't free here! this pointer might be no longer valid!
+-		dev_kfree_skb(skb);
+-		*/
+ 		brdev->stats.tx_errors++;
+ 		brdev->stats.tx_fifo_errors++;
+ 	}
+@@ -217,12 +258,11 @@
+ 	return &BRPRIV(dev)->stats;
+ }
+ 
+-
+ /*
+  * We remember when the MAC gets set, so we don't override it later with
+  * the ESI of the ATM card of the first VC
+  */
+-static int (*my_eth_mac_addr)(struct net_device *, void *);
++static int (*my_eth_mac_addr) (struct net_device *, void *);
+ static int br2684_mac_addr(struct net_device *dev, void *p)
+ {
+ 	int err = my_eth_mac_addr(dev, p);
+@@ -233,7 +273,7 @@
+ 
+ #ifdef CONFIG_ATM_BR2684_IPFILTER
+ /* this IOCTL is experimental. */
+-static int br2684_setfilt(struct atm_vcc *atmvcc, void __user *arg)
++static int br2684_setfilt(struct atm_vcc *atmvcc, void __user * arg)
+ {
+ 	struct br2684_vcc *brvcc;
+ 	struct br2684_filter_set fs;
+@@ -243,13 +283,12 @@
+ 	if (fs.ifspec.method != BR2684_FIND_BYNOTHING) {
+ 		/*
+ 		 * This is really a per-vcc thing, but we can also search
+-		 * by device
++		 * by device.
+ 		 */
+ 		struct br2684_dev *brdev;
+ 		read_lock(&devs_lock);
+ 		brdev = BRPRIV(br2684_find_dev(&fs.ifspec));
+-		if (brdev == NULL || list_empty(&brdev->brvccs) ||
+-		    brdev->brvccs.next != brdev->brvccs.prev)  /* >1 VCC */
++		if (brdev == NULL || list_empty(&brdev->brvccs) || brdev->brvccs.next != brdev->brvccs.prev)	/* >1 VCC */
+ 			brvcc = NULL;
+ 		else
+ 			brvcc = list_entry_brvcc(brdev->brvccs.next);
+@@ -267,15 +306,16 @@
+ packet_fails_filter(__be16 type, struct br2684_vcc *brvcc, struct sk_buff *skb)
+ {
+ 	if (brvcc->filter.netmask == 0)
+-		return 0;			/* no filter in place */
++		return 0;	/* no filter in place */
+ 	if (type == htons(ETH_P_IP) &&
+-	    (((struct iphdr *) (skb->data))->daddr & brvcc->filter.
++	    (((struct iphdr *)(skb->data))->daddr & brvcc->filter.
+ 	     netmask) == brvcc->filter.prefix)
+ 		return 0;
+ 	if (type == htons(ETH_P_ARP))
+ 		return 0;
+-	/* TODO: we should probably filter ARPs too.. don't want to have
+-	 *   them returning values that don't make sense, or is that ok?
++	/*
++	 * TODO: we should probably filter ARPs too.. don't want to have
++	 * them returning values that don't make sense, or is that ok?
+ 	 */
+ 	return 1;		/* drop */
+ }
+@@ -299,7 +339,6 @@
+ 	struct br2684_vcc *brvcc = BR2684_VCC(atmvcc);
+ 	struct net_device *net_dev = brvcc->device;
+ 	struct br2684_dev *brdev = BRPRIV(net_dev);
+-	int plen = sizeof(llc_oui_pid_pad) + ETH_HLEN;
+ 
+ 	pr_debug("br2684_push\n");
+ 
+@@ -320,35 +359,58 @@
+ 	atm_return(atmvcc, skb->truesize);
+ 	pr_debug("skb from brdev %p\n", brdev);
+ 	if (brvcc->encaps == e_llc) {
+-		/* let us waste some time for checking the encapsulation.
+-		   Note, that only 7 char is checked so frames with a valid FCS
+-		   are also accepted (but FCS is not checked of course) */
+-		if (memcmp(skb->data, llc_oui_pid_pad, 7)) {
++
++		if (skb->len > 7 && skb->data[7] == 0x01)
++			__skb_trim(skb, skb->len - 4);
++
++		/* accept packets that have "ipv[46]" in the snap header */
++		if ((skb->len >= (sizeof(llc_oui_ipv4)))
++		    &&
++		    (memcmp
++		     (skb->data, llc_oui_ipv4,
++		      sizeof(llc_oui_ipv4) - BR2684_ETHERTYPE_LEN) == 0)) {
++			if (memcmp
++			    (skb->data + 6, ethertype_ipv6,
++			     sizeof(ethertype_ipv6)) == 0)
++				skb->protocol = __constant_htons(ETH_P_IPV6);
++			else if (memcmp
++				 (skb->data + 6, ethertype_ipv4,
++				  sizeof(ethertype_ipv4)) == 0)
++				skb->protocol = __constant_htons(ETH_P_IP);
++			else {
++				brdev->stats.rx_errors++;
++				dev_kfree_skb(skb);
++				return;
++			}
++			skb_pull(skb, sizeof(llc_oui_ipv4));
++			skb_reset_network_header(skb);
++			skb->pkt_type = PACKET_HOST;
++			/*
++			 * Let us waste some time for checking the encapsulation.
++			 * Note, that only 7 char is checked so frames with a valid FCS
++			 * are also accepted (but FCS is not checked of course).
++			 */
++		} else if ((skb->len >= sizeof(llc_oui_pid_pad)) &&
++			   (memcmp(skb->data, llc_oui_pid_pad, 7) == 0)) {
++			skb_pull(skb, sizeof(llc_oui_pid_pad));
++			skb->protocol = eth_type_trans(skb, net_dev);
++		} else {
+ 			brdev->stats.rx_errors++;
+ 			dev_kfree_skb(skb);
+ 			return;
+ 		}
+ 
+-		/* Strip FCS if present */
+-		if (skb->len > 7 && skb->data[7] == 0x01)
+-			__skb_trim(skb, skb->len - 4);
+ 	} else {
+-		plen = PADLEN + ETH_HLEN;	/* pad, dstmac,srcmac, ethtype */
+ 		/* first 2 chars should be 0 */
+ 		if (*((u16 *) (skb->data)) != 0) {
+ 			brdev->stats.rx_errors++;
+ 			dev_kfree_skb(skb);
+ 			return;
+ 		}
+-	}
+-	if (skb->len < plen) {
+-		brdev->stats.rx_errors++;
+-		dev_kfree_skb(skb);	/* dev_ not needed? */
+-		return;
++		skb_pull(skb, BR2684_PAD_LEN + ETH_HLEN);	/* pad, dstmac, srcmac, ethtype */
++		skb->protocol = eth_type_trans(skb, net_dev);
+ 	}
+ 
+-	skb_pull(skb, plen - ETH_HLEN);
+-	skb->protocol = eth_type_trans(skb, net_dev);
+ #ifdef CONFIG_ATM_BR2684_IPFILTER
+ 	if (unlikely(packet_fails_filter(skb->protocol, brvcc, skb))) {
+ 		brdev->stats.rx_dropped++;
+@@ -372,11 +434,12 @@
+ 	netif_rx(skb);
+ }
+ 
+-static int br2684_regvcc(struct atm_vcc *atmvcc, void __user *arg)
++/*
++ * Assign a vcc to a dev
++ * Note: we do not have explicit unassign, but look at _push()
++ */
++static int br2684_regvcc(struct atm_vcc *atmvcc, void __user * arg)
+ {
+-/* assign a vcc to a dev
+-Note: we do not have explicit unassign, but look at _push()
+-*/
+ 	int err;
+ 	struct br2684_vcc *brvcc;
+ 	struct sk_buff *skb;
+@@ -395,7 +458,7 @@
+ 	net_dev = br2684_find_dev(&be.ifspec);
+ 	if (net_dev == NULL) {
+ 		printk(KERN_ERR
+-		    "br2684: tried to attach to non-existant device\n");
++		       "br2684: tried to attach to non-existant device\n");
+ 		err = -ENXIO;
+ 		goto error;
+ 	}
+@@ -411,13 +474,15 @@
+ 	}
+ 	if (be.fcs_in != BR2684_FCSIN_NO || be.fcs_out != BR2684_FCSOUT_NO ||
+ 	    be.fcs_auto || be.has_vpiid || be.send_padding || (be.encaps !=
+-	    BR2684_ENCAPS_VC && be.encaps != BR2684_ENCAPS_LLC) ||
+-	    be.min_size != 0) {
++							       BR2684_ENCAPS_VC
++							       && be.encaps !=
++							       BR2684_ENCAPS_LLC)
++	    || be.min_size != 0) {
+ 		err = -EINVAL;
+ 		goto error;
+ 	}
+-	pr_debug("br2684_regvcc vcc=%p, encaps=%d, brvcc=%p\n", atmvcc, be.encaps,
+-		brvcc);
++	pr_debug("br2684_regvcc vcc=%p, encaps=%d, brvcc=%p\n", atmvcc,
++		 be.encaps, brvcc);
+ 	if (list_empty(&brdev->brvccs) && !brdev->mac_was_set) {
+ 		unsigned char *esi = atmvcc->dev->esi;
+ 		if (esi[0] | esi[1] | esi[2] | esi[3] | esi[4] | esi[5])
+@@ -430,7 +495,7 @@
+ 	brvcc->device = net_dev;
+ 	brvcc->atmvcc = atmvcc;
+ 	atmvcc->user_back = brvcc;
+-	brvcc->encaps = (enum br2684_encaps) be.encaps;
++	brvcc->encaps = (enum br2684_encaps)be.encaps;
+ 	brvcc->old_push = atmvcc->push;
+ 	barrier();
+ 	atmvcc->push = br2684_push;
+@@ -461,7 +526,7 @@
+ 	}
+ 	__module_get(THIS_MODULE);
+ 	return 0;
+-    error:
++      error:
+ 	write_unlock_irq(&devs_lock);
+ 	kfree(brvcc);
+ 	return err;
+@@ -482,25 +547,52 @@
+ 	INIT_LIST_HEAD(&brdev->brvccs);
+ }
+ 
+-static int br2684_create(void __user *arg)
++static void br2684_setup_routed(struct net_device *netdev)
++{
++	struct br2684_dev *brdev = BRPRIV(netdev);
++	brdev->net_dev = netdev;
++
++	netdev->hard_header_len = 0;
++	my_eth_mac_addr = netdev->set_mac_address;
++	netdev->set_mac_address = br2684_mac_addr;
++	netdev->hard_start_xmit = br2684_start_xmit;
++	netdev->get_stats = br2684_get_stats;
++	netdev->addr_len = 0;
++	netdev->mtu = 1500;
++	netdev->type = ARPHRD_PPP;
++	netdev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
++	netdev->tx_queue_len = 100;
++	INIT_LIST_HEAD(&brdev->brvccs);
++}
++
++static int br2684_create(void __user * arg)
+ {
+ 	int err;
+ 	struct net_device *netdev;
+ 	struct br2684_dev *brdev;
+ 	struct atm_newif_br2684 ni;
++	enum br2684_payload payload;
+ 
+ 	pr_debug("br2684_create\n");
+ 
+ 	if (copy_from_user(&ni, arg, sizeof ni)) {
+ 		return -EFAULT;
+ 	}
++
++	if (ni.media & BR2684_FLAG_ROUTED)
++		payload = p_routed;
++	else
++		payload = p_bridged;
++	ni.media &= 0xffff;	/* strip flags */
++
+ 	if (ni.media != BR2684_MEDIA_ETHERNET || ni.mtu != 1500) {
+ 		return -EINVAL;
+ 	}
+ 
+ 	netdev = alloc_netdev(sizeof(struct br2684_dev),
+ 			      ni.ifname[0] ? ni.ifname : "nas%d",
+-			      br2684_setup);
++			      (payload == p_routed) ?
++			      br2684_setup_routed : br2684_setup);
+ 	if (!netdev)
+ 		return -ENOMEM;
+ 
+@@ -516,6 +608,7 @@
+ 	}
+ 
+ 	write_lock_irq(&devs_lock);
++	brdev->payload = payload;
+ 	brdev->number = list_empty(&br2684_devs) ? 1 :
+ 	    BRPRIV(list_entry_brdev(br2684_devs.prev))->number + 1;
+ 	list_add_tail(&brdev->br2684_devs, &br2684_devs);
+@@ -528,16 +621,16 @@
+  * -ENOIOCTLCMD for any unrecognized ioctl
+  */
+ static int br2684_ioctl(struct socket *sock, unsigned int cmd,
+-	unsigned long arg)
++			unsigned long arg)
+ {
+ 	struct atm_vcc *atmvcc = ATM_SD(sock);
+ 	void __user *argp = (void __user *)arg;
++	atm_backend_t b;
+ 
+ 	int err;
+-	switch(cmd) {
++	switch (cmd) {
+ 	case ATM_SETBACKEND:
+-	case ATM_NEWBACKENDIF: {
+-		atm_backend_t b;
++	case ATM_NEWBACKENDIF:
+ 		err = get_user(b, (atm_backend_t __user *) argp);
+ 		if (err)
+ 			return -EFAULT;
+@@ -549,7 +642,6 @@
+ 			return br2684_regvcc(atmvcc, argp);
+ 		else
+ 			return br2684_create(argp);
+-		}
+ #ifdef CONFIG_ATM_BR2684_IPFILTER
+ 	case BR2684_SETFILT:
+ 		if (atmvcc->push != br2684_push)
+@@ -557,6 +649,7 @@
+ 		if (!capable(CAP_NET_ADMIN))
+ 			return -EPERM;
+ 		err = br2684_setfilt(atmvcc, argp);
++
+ 		return err;
+ #endif /* CONFIG_ATM_BR2684_IPFILTER */
+ 	}
+@@ -564,24 +657,25 @@
+ }
+ 
+ static struct atm_ioctl br2684_ioctl_ops = {
+-	.owner	= THIS_MODULE,
+-	.ioctl	= br2684_ioctl,
++	.owner = THIS_MODULE,
++	.ioctl = br2684_ioctl,
+ };
+ 
+-
+ #ifdef CONFIG_PROC_FS
+-static void *br2684_seq_start(struct seq_file *seq, loff_t *pos)
++static void *br2684_seq_start(struct seq_file *seq, loff_t * pos)
++	__acquires(devs_lock)
+ {
+ 	read_lock(&devs_lock);
+ 	return seq_list_start(&br2684_devs, *pos);
+ }
+ 
+-static void *br2684_seq_next(struct seq_file *seq, void *v, loff_t *pos)
++static void *br2684_seq_next(struct seq_file *seq, void *v, loff_t * pos)
+ {
+ 	return seq_list_next(v, &br2684_devs, pos);
+ }
+ 
+ static void br2684_seq_stop(struct seq_file *seq, void *v)
++	__releases(devs_lock)
+ {
+ 	read_unlock(&devs_lock);
+ }
+@@ -589,7 +683,7 @@
+ static int br2684_seq_show(struct seq_file *seq, void *v)
+ {
+ 	const struct br2684_dev *brdev = list_entry(v, struct br2684_dev,
+-			br2684_devs);
++						    br2684_devs);
+ 	const struct net_device *net_dev = brdev->net_dev;
+ 	const struct br2684_vcc *brvcc;
+ 	DECLARE_MAC_BUF(mac);
+@@ -601,21 +695,19 @@
+ 		   brdev->mac_was_set ? "set" : "auto");
+ 
+ 	list_for_each_entry(brvcc, &brdev->brvccs, brvccs) {
+-		seq_printf(seq, "  vcc %d.%d.%d: encaps=%s"
+-				    ", failed copies %u/%u"
+-				    "\n", brvcc->atmvcc->dev->number,
+-				    brvcc->atmvcc->vpi, brvcc->atmvcc->vci,
+-				    (brvcc->encaps == e_llc) ? "LLC" : "VC"
+-				    , brvcc->copies_failed
+-				    , brvcc->copies_needed
+-				    );
++		seq_printf(seq, "  vcc %d.%d.%d: encaps=%s payload=%s"
++			   ", failed copies %u/%u"
++			   "\n", brvcc->atmvcc->dev->number,
++			   brvcc->atmvcc->vpi, brvcc->atmvcc->vci,
++			   (brvcc->encaps == e_llc) ? "LLC" : "VC",
++			   (brdev->payload == p_bridged) ? "bridged" : "routed",
++			   brvcc->copies_failed, brvcc->copies_needed);
+ #ifdef CONFIG_ATM_BR2684_IPFILTER
+ #define b1(var, byte)	((u8 *) &brvcc->filter.var)[byte]
+ #define bs(var)		b1(var, 0), b1(var, 1), b1(var, 2), b1(var, 3)
+-			if (brvcc->filter.netmask != 0)
+-				seq_printf(seq, "    filter=%d.%d.%d.%d/"
+-						"%d.%d.%d.%d\n",
+-						bs(prefix), bs(netmask));
++		if (brvcc->filter.netmask != 0)
++			seq_printf(seq, "    filter=%d.%d.%d.%d/"
++				   "%d.%d.%d.%d\n", bs(prefix), bs(netmask));
+ #undef bs
+ #undef b1
+ #endif /* CONFIG_ATM_BR2684_IPFILTER */
+@@ -625,9 +717,9 @@
+ 
+ static const struct seq_operations br2684_seq_ops = {
+ 	.start = br2684_seq_start,
+-	.next  = br2684_seq_next,
+-	.stop  = br2684_seq_stop,
+-	.show  = br2684_seq_show,
++	.next = br2684_seq_next,
++	.stop = br2684_seq_stop,
++	.show = br2684_seq_show,
+ };
+ 
+ static int br2684_proc_open(struct inode *inode, struct file *file)
+@@ -636,26 +728,28 @@
+ }
+ 
+ static const struct file_operations br2684_proc_ops = {
+-	.owner   = THIS_MODULE,
+-	.open    = br2684_proc_open,
+-	.read    = seq_read,
+-	.llseek  = seq_lseek,
++	.owner = THIS_MODULE,
++	.open = br2684_proc_open,
++	.read = seq_read,
++	.llseek = seq_lseek,
+ 	.release = seq_release,
+ };
+ 
+ extern struct proc_dir_entry *atm_proc_root;	/* from proc.c */
+-#endif
++#endif /* CONFIG_PROC_FS */
+ 
+ static int __init br2684_init(void)
+ {
+ #ifdef CONFIG_PROC_FS
+ 	struct proc_dir_entry *p;
++
+ 	if ((p = create_proc_entry("br2684", 0, atm_proc_root)) == NULL)
+-		return -ENOMEM;
+-	p->proc_fops = &br2684_proc_ops;
++        return -ENOMEM;
++        p->proc_fops = &br2684_proc_ops;
+ #endif
+-	register_atm_ioctl(&br2684_ioctl_ops);
+-	return 0;
++        register_atm_ioctl(&br2684_ioctl_ops);
++        return 0;
++                                        
+ }
+ 
+ static void __exit br2684_exit(void)
+@@ -689,3 +783,4 @@
+ MODULE_AUTHOR("Marcell GAL");
+ MODULE_DESCRIPTION("RFC2684 bridged protocols over ATM/AAL5");
+ MODULE_LICENSE("GPL");
++
Index: package/br2684ctl/files/br2684ctl
===================================================================
--- package/br2684ctl/files/br2684ctl	(revision 10695)
+++ package/br2684ctl/files/br2684ctl	(working copy)
@@ -14,11 +14,16 @@
 	config_get vpi "$cfg" vpi
 	config_get vci "$cfg" vci
 	config_get encaps "$cfg" encaps
+	config_get payload "cfg" payload
 	case "$encaps" in
 		1|vc) encaps=1;;
 		*) encaps=0;;
 	esac
-	br2684ctl -b -c "$unit" -e "$encaps" -a "${atmdev:+$atmdev.}${vpi:-8}.${vci:-35}"
+        case "$payload" in
+                1|bridged) payload=1;;
+                *) payload=0;;
+        esac
+	br2684ctl -b -c "$unit" -e "$encaps" -p "$payload" -a "${atmdev:+$atmdev.}${vpi:-8}.${vci:-35}"	
 }
 
 start() {
Index: package/br2684ctl/patches/101-routed_support.patch
===================================================================
--- package/br2684ctl/patches/101-routed_support.patch	(revision 0)
+++ package/br2684ctl/patches/101-routed_support.patch	(revision 0)
@@ -0,0 +1,301 @@
+diff -Nu br2684ctl-20040226.orig/br2684ctl.c br2684ctl.orig/br2684ctl.c
+--- br2684ctl-20040226.orig/br2684ctl.c	2008-03-25 22:26:59.000000000 +0000
++++ br2684ctl.orig/br2684ctl.c	2008-03-31 10:11:06.000000000 +0100
+@@ -10,6 +10,10 @@
+ #include <atm.h>
+ #include <linux/atmdev.h>
+ #include <linux/atmbr2684.h>
++#ifndef BR2684_FLAG_ROUTED
++#warning "Kernel missing routed support for br2684"
++#define BR2684_FLAG_ROUTED    (1<<16) /* payload is routed, not bridged */
++#endif
+ 
+ /* Written by Marcell GAL <[EMAIL PROTECTED]> to make use of the */
+ /* ioctls defined in the br2684... kernel patch */
+@@ -28,26 +32,35 @@
+ #define LOG_OPTION     LOG_PERROR|LOG_PID
+ #define LOG_FACILITY   LOG_LOCAL2
+ 
++struct br2684_params {
++  int itfnum;
++  int encap;
++  int sndbuf;
++  int payload;
++  char *astr; /* temporary */
++  struct atm_qos reqqos;
++};
++
+ 
+ int lastsock, lastitf;
+ 
+ 
+-void fatal(const char *str, int i)
++void fatal(const char *str, int err)
+ {
+-  syslog (LOG_ERR,"Fatal: %s",str);
++  syslog (LOG_ERR,"Fatal: %s; %s", str, strerror(err));
+   exit(-2);
+ };
+ 
+ 
+ void exitFunc(void)
+ {
+-  syslog (LOG_NOTICE,"Daemon terminated\n");
++  syslog (LOG_NOTICE,"Daemon terminated");
+ }
+ 
+ 
+ void int_signal(int dummy)
+ {
+-  syslog (LOG_INFO,"Killed by a signal\n");
++  syslog (LOG_INFO,"Killed by a signal");
+   exit(0);
+ }
+ 
+@@ -58,7 +71,7 @@
+ 
+   if (num < 0) return -1;
+ 
+-  snprintf(name, 20, "/var/run/nas%d.pid", num);
++  snprintf(name, 32, "/var/run/br2684ctl-nas%d.pid", num);
+   pidfile = fopen(name, "w");
+   if (pidfile == NULL) return -1;
+   fprintf(pidfile, "%d", getpid());
+@@ -67,9 +80,9 @@
+   return 0;
+ }
+ 
+-int create_br(char *nstr)
++int create_br(int itfnum, int payload)
+ {
+-  int num, err;
++  int err;
+   
+   if(lastsock<0) {
+     lastsock = socket(PF_ATMPVC, SOCK_DGRAM, ATM_AAL5);
+@@ -78,31 +91,36 @@
+     syslog(LOG_ERR, "socket creation failed: %s",strerror(errno));
+   } else {
+     /* create the device with ioctl: */
+-    num=atoi(nstr);
+-    if( num>=0 && num<1234567890){
++    if( itfnum>=0 && itfnum<1234567890){
+       struct atm_newif_br2684 ni;
+       ni.backend_num = ATM_BACKEND_BR2684;
+       ni.media = BR2684_MEDIA_ETHERNET;
++#ifdef BR2684_FLAG_ROUTED
++      if (payload == 0)
++        ni.media |= BR2684_FLAG_ROUTED;
++#endif
+       ni.mtu = 1500;
+-      sprintf(ni.ifname, "nas%d", num);
++      sprintf(ni.ifname, "nas%d", itfnum);
+       err=ioctl (lastsock, ATM_NEWBACKENDIF, &ni);
+   
+       if (err == 0)
+-	syslog(LOG_NOTICE, "Interface \"%s\" created sucessfully\n",ni.ifname);
++	syslog(LOG_NOTICE, "Interface \"%s\" created sucessfully",ni.ifname);
+       else
+-	syslog(LOG_INFO, "Interface \"%s\" could not be created, reason: %s\n",
++	syslog(LOG_INFO, "Interface \"%s\" could not be created, reason: %s",
+ 	       ni.ifname,
+ 	       strerror(errno));
+-      lastitf=num;	/* even if we didn't create, because existed, assign_vcc wil want to know it! */
++      lastitf=itfnum;	/* even if we didn't create, because existed, 
++			assign_vcc wil want to know it! */
+     } else {
+-      syslog(LOG_ERR,"err: strange interface number %d", num );
++      syslog(LOG_ERR,"err: strange interface number %d", itfnum );
+     }
+   }
+   return 0;
+ }
+ 
+ 
+-int assign_vcc(char *astr, int encap, int bufsize, struct atm_qos qos)
++int assign_vcc(char *astr, int encap, int payload,
++               int bufsize, struct atm_qos qos)
+ {
+     int err;
+     struct sockaddr_atmpvc addr;
+@@ -112,21 +130,17 @@
+     memset(&addr, 0, sizeof(addr));
+     err=text2atm(astr,(struct sockaddr *)(&addr), sizeof(addr), T2A_PVC);
+     if (err!=0)
+-      syslog(LOG_ERR,"Could not parse ATM parameters (error=%d)\n",err);
++      syslog(LOG_ERR,"Could not parse ATM parameters (error=%d)",err);
+     
+-#if 0
+-    addr.sap_family = AF_ATMPVC;
+-    addr.sap_addr.itf = itf;
+-    addr.sap_addr.vpi = 0;
+-    addr.sap_addr.vci = vci;
+-#endif
+-    syslog(LOG_NOTICE,"Communicating over ATM %d.%d.%d, encapsulation: %s\n", addr.sap_addr.itf,
++    syslog(LOG_NOTICE,"Communicating over ATM %d.%d.%d, encapsulation: %s",
++	   addr.sap_addr.itf,
+ 	   addr.sap_addr.vpi,
+ 	   addr.sap_addr.vci,
+ 	   encap?"VC mux":"LLC");
+     
+     if ((fd = socket(PF_ATMPVC, SOCK_DGRAM, ATM_AAL5)) < 0)
+-      syslog(LOG_ERR,"failed to create socket %d, reason: %s", errno,strerror(errno));
++      syslog(LOG_ERR,"failed to create socket %d, reason: %s", 
++	     errno,strerror(errno));
+     
+     if (qos.aal == 0) {
+       qos.aal                     = ATM_AAL5;
+@@ -137,7 +151,7 @@
+     }
+ 
+     if ( (err=setsockopt(fd,SOL_SOCKET,SO_SNDBUF, &bufsize ,sizeof(bufsize))) )
+-      syslog(LOG_ERR,"setsockopt SO_SNDBUF: (%d) %s\n",err, strerror(err));
++      syslog(LOG_ERR,"setsockopt SO_SNDBUF: (%d) %s",err, strerror(err));
+     
+     if (setsockopt(fd, SOL_ATM, SO_ATMQOS, &qos, sizeof(qos)) < 0)
+       syslog(LOG_ERR,"setsockopt SO_ATMQOS %d", errno);
+@@ -145,7 +159,7 @@
+     err = connect(fd, (struct sockaddr*)&addr, sizeof(struct sockaddr_atmpvc));
+     
+     if (err < 0)
+-      fatal("failed to connect on socket", err);
++      fatal("failed to connect on socket", errno);
+     
+     /* attach the vcc to device: */
+     
+@@ -169,10 +183,30 @@
+     return fd ;
+ }
+ 
++void start_interface(struct br2684_params* params)
++{
++  if (params->astr==NULL) {
++    syslog(LOG_ERR, "Required ATM parameters not specified.");
++    exit(1);
++  }
++
++  create_br(params->itfnum, params->payload);
++  assign_vcc(params->astr, params->encap, params->payload, params->sndbuf,
++	     params->reqqos);
++}
++
+ 
+ void usage(char *s)
+ {
+-  printf("usage: %s [-b] [[-c number] [-e 0|1] [-s sndbuf] [-q qos] [-a [itf.]vpi.vci]*]*\n", s);
++  printf("usage: %s [-b] [[-c number] [-e 0|1] [-s sndbuf] [-q qos] [-p 0|1] "
++        "[-a [itf.]vpi.vci]*]*\n"
++           " -b               = run in background (daemonize)\n"
++           " -c <num>         = use interface nas<num>\n"
++           " -e 0|1           = encapsulation (0=LLC, 1=VC Mux)\n"
++           " -p 0|1           = payload type (0=routed,1=bridged)\n"
++           " -s <num>         = set sndbuf (send buffer) size (default 8192)\n"
++           " -a [itf.]vpi.vci = ATM interface no, VPI, VCI\n",
++           s);
+   exit(1);
+ }
+ 
+@@ -180,47 +214,63 @@
+ 
+ int main (int argc, char **argv)
+ {
+-  int c, background=0, encap=0, sndbuf=8192;
+-  struct atm_qos reqqos;
+-  int itfnum;
++  int c, background=0;
++
++  struct br2684_params params;
++  params.itfnum=-1;
++  params.encap=0;
++  params.sndbuf=8192;
++  params.payload=1;
++  params.astr=NULL;
++  memset(&params.reqqos, 0, sizeof(params.reqqos));
++  
+   lastsock=-1;
+   lastitf=0;
+   
+   /* st qos to 0 */
+-  memset(&reqqos, 0, sizeof(reqqos));
+ 
+   openlog (LOG_NAME,LOG_OPTION,LOG_FACILITY);
+   if (argc>1)
+-    while ((c = getopt(argc, argv,"q:a:bc:e:s:?h")) !=EOF)
++    while ((c = getopt(argc, argv,"q:a:bc:e:s:p:?h")) !=EOF)
+       switch (c) {
+       case 'q':
+ 	printf ("optarg : %s",optarg);
+-	if (text2qos(optarg,&reqqos,0)) fprintf(stderr,"QOS parameter invalid\n"); 
++	if (text2qos(optarg,&params.reqqos,0))
++	  fprintf(stderr,"QOS parameter invalid\n");
+ 	break;
+       case 'a':
+-	assign_vcc(optarg, encap, sndbuf, reqqos);
++	params.astr=optarg;
+ 	break;
+       case 'b':
+ 	background=1;
+ 	break;
+       case 'c':
+-	create_br(optarg);
+-	itfnum = atoi(optarg);
++	/* temporary, to make it work with multiple interfaces: */
++	if (params.itfnum>=0) start_interface(&params);
++	params.itfnum= atoi(optarg);
+ 	break;
+       case 'e':
+-	encap=(atoi(optarg));
+-	if(encap<0){
+-	  syslog (LOG_ERR, "invalid encapsulation: %s:\n",optarg);
+-	  encap=0;
++	params.encap=(atoi(optarg));
++	if(params.encap<0){
++	  syslog (LOG_ERR, "invalid encapsulation: %s:",optarg);
++	  params.encap=0;
+ 	}
+ 	break;
+       case 's':
+-	sndbuf=(atoi(optarg));
+-	if(sndbuf<0){
+-	  syslog(LOG_ERR, "Invalid sndbuf: %s, using size of 8192 instead\n",optarg);
+-	  sndbuf=8192;
++	params.sndbuf=(atoi(optarg));
++	if(params.sndbuf<0){
++	  syslog(LOG_ERR, "Invalid sndbuf: %s, using size of 8192 instead", 
++		 optarg);
++	  params.sndbuf=8192;
+ 	}
+ 	break;
++      case 'p':	/* payload type: routed (0) or bridged (1) */
++#ifdef BR2684_FLAG_ROUTED
++	params.payload = atoi(optarg);
++	break;
++#else
++	syslog(LOG_ERR, "payload option not supported.");
++#endif
+       case '?':
+       case 'h':
+       default:
+@@ -231,6 +281,8 @@
+ 
+   if (argc != optind) usage(argv[0]);
+   
++  start_interface(&params);  
++
+   if(lastsock>=0) close(lastsock);
+   
+   if (background) {
+@@ -268,11 +320,11 @@
+     
+   }
+   
+-  create_pidfile(itfnum);
++  create_pidfile(params.itfnum);
+   signal(SIGINT, int_signal);
+   signal(SIGTERM, int_signal);
+ 
+-  syslog (LOG_INFO, "RFC 1483/2684 bridge daemon started\n");	
++  syslog (LOG_INFO, "RFC 1483/2684 bridge daemon started");
+   atexit (exitFunc);
+   
+   while (1) pause();	/* to keep the sockets... */
_______________________________________________
openwrt-devel mailing list
openwrt-devel@lists.openwrt.org
http://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel

Reply via email to