aboutsummaryrefslogtreecommitdiffstats
path: root/net/atm
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /net/atm
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'net/atm')
-rw-r--r--net/atm/Makefile18
-rw-r--r--net/atm/addr.c134
-rw-r--r--net/atm/addr.h18
-rw-r--r--net/atm/atm_misc.c106
-rw-r--r--net/atm/br2684.c824
-rw-r--r--net/atm/clip.c1045
-rw-r--r--net/atm/common.c804
-rw-r--r--net/atm/common.h50
-rw-r--r--net/atm/ioctl.c139
-rw-r--r--net/atm/ipcommon.c61
-rw-r--r--net/atm/ipcommon.h22
-rw-r--r--net/atm/lec.c2538
-rw-r--r--net/atm/lec.h142
-rw-r--r--net/atm/lec_arpc.h92
-rw-r--r--net/atm/mpc.c1514
-rw-r--r--net/atm/mpc.h53
-rw-r--r--net/atm/mpoa_caches.c576
-rw-r--r--net/atm/mpoa_caches.h96
-rw-r--r--net/atm/mpoa_proc.c305
-rw-r--r--net/atm/pppoatm.c369
-rw-r--r--net/atm/proc.c514
-rw-r--r--net/atm/protocols.h13
-rw-r--r--net/atm/pvc.c155
-rw-r--r--net/atm/raw.c98
-rw-r--r--net/atm/resources.c432
-rw-r--r--net/atm/resources.h46
-rw-r--r--net/atm/signaling.c280
-rw-r--r--net/atm/signaling.h30
-rw-r--r--net/atm/svc.c674
29 files changed, 11148 insertions, 0 deletions
diff --git a/net/atm/Makefile b/net/atm/Makefile
new file mode 100644
index 000000000000..d5818751f6ba
--- /dev/null
+++ b/net/atm/Makefile
@@ -0,0 +1,18 @@
1#
2# Makefile for the ATM Protocol Families.
3#
4
5atm-y := addr.o pvc.o signaling.o svc.o ioctl.o common.o atm_misc.o raw.o resources.o
6mpoa-objs := mpc.o mpoa_caches.o mpoa_proc.o
7
8obj-$(CONFIG_ATM) += atm.o
9obj-$(CONFIG_ATM_CLIP) += clip.o
10atm-$(subst m,y,$(CONFIG_ATM_CLIP)) += ipcommon.o
11obj-$(CONFIG_ATM_BR2684) += br2684.o
12atm-$(subst m,y,$(CONFIG_ATM_BR2684)) += ipcommon.o
13atm-$(subst m,y,$(CONFIG_NET_SCH_ATM)) += ipcommon.o
14atm-$(CONFIG_PROC_FS) += proc.o
15
16obj-$(CONFIG_ATM_LANE) += lec.o
17obj-$(CONFIG_ATM_MPOA) += mpoa.o
18obj-$(CONFIG_PPPOATM) += pppoatm.o
diff --git a/net/atm/addr.c b/net/atm/addr.c
new file mode 100644
index 000000000000..1c8867f7f54a
--- /dev/null
+++ b/net/atm/addr.c
@@ -0,0 +1,134 @@
1/* net/atm/addr.c - Local ATM address registry */
2
3/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
4
5#include <linux/atm.h>
6#include <linux/atmdev.h>
7#include <linux/sched.h>
8#include <asm/uaccess.h>
9
10#include "signaling.h"
11#include "addr.h"
12
13static int check_addr(struct sockaddr_atmsvc *addr)
14{
15 int i;
16
17 if (addr->sas_family != AF_ATMSVC)
18 return -EAFNOSUPPORT;
19 if (!*addr->sas_addr.pub)
20 return *addr->sas_addr.prv ? 0 : -EINVAL;
21 for (i = 1; i < ATM_E164_LEN + 1; i++) /* make sure it's \0-terminated */
22 if (!addr->sas_addr.pub[i])
23 return 0;
24 return -EINVAL;
25}
26
27static int identical(struct sockaddr_atmsvc *a, struct sockaddr_atmsvc *b)
28{
29 if (*a->sas_addr.prv)
30 if (memcmp(a->sas_addr.prv, b->sas_addr.prv, ATM_ESA_LEN))
31 return 0;
32 if (!*a->sas_addr.pub)
33 return !*b->sas_addr.pub;
34 if (!*b->sas_addr.pub)
35 return 0;
36 return !strcmp(a->sas_addr.pub, b->sas_addr.pub);
37}
38
39static void notify_sigd(struct atm_dev *dev)
40{
41 struct sockaddr_atmpvc pvc;
42
43 pvc.sap_addr.itf = dev->number;
44 sigd_enq(NULL, as_itf_notify, NULL, &pvc, NULL);
45}
46
47void atm_reset_addr(struct atm_dev *dev)
48{
49 unsigned long flags;
50 struct atm_dev_addr *this, *p;
51
52 spin_lock_irqsave(&dev->lock, flags);
53 list_for_each_entry_safe(this, p, &dev->local, entry)
54 kfree(this);
55 spin_unlock_irqrestore(&dev->lock, flags);
56 notify_sigd(dev);
57}
58
59int atm_add_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr)
60{
61 unsigned long flags;
62 struct atm_dev_addr *this;
63 int error;
64
65 error = check_addr(addr);
66 if (error)
67 return error;
68 spin_lock_irqsave(&dev->lock, flags);
69 list_for_each_entry(this, &dev->local, entry) {
70 if (identical(&this->addr, addr)) {
71 spin_unlock_irqrestore(&dev->lock, flags);
72 return -EEXIST;
73 }
74 }
75 this = kmalloc(sizeof(struct atm_dev_addr), GFP_ATOMIC);
76 if (!this) {
77 spin_unlock_irqrestore(&dev->lock, flags);
78 return -ENOMEM;
79 }
80 this->addr = *addr;
81 list_add(&this->entry, &dev->local);
82 spin_unlock_irqrestore(&dev->lock, flags);
83 notify_sigd(dev);
84 return 0;
85}
86
87int atm_del_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr)
88{
89 unsigned long flags;
90 struct atm_dev_addr *this;
91 int error;
92
93 error = check_addr(addr);
94 if (error)
95 return error;
96 spin_lock_irqsave(&dev->lock, flags);
97 list_for_each_entry(this, &dev->local, entry) {
98 if (identical(&this->addr, addr)) {
99 list_del(&this->entry);
100 spin_unlock_irqrestore(&dev->lock, flags);
101 kfree(this);
102 notify_sigd(dev);
103 return 0;
104 }
105 }
106 spin_unlock_irqrestore(&dev->lock, flags);
107 return -ENOENT;
108}
109
110int atm_get_addr(struct atm_dev *dev, struct sockaddr_atmsvc __user * buf,
111 size_t size)
112{
113 unsigned long flags;
114 struct atm_dev_addr *this;
115 int total = 0, error;
116 struct sockaddr_atmsvc *tmp_buf, *tmp_bufp;
117
118 spin_lock_irqsave(&dev->lock, flags);
119 list_for_each_entry(this, &dev->local, entry)
120 total += sizeof(struct sockaddr_atmsvc);
121 tmp_buf = tmp_bufp = kmalloc(total, GFP_ATOMIC);
122 if (!tmp_buf) {
123 spin_unlock_irqrestore(&dev->lock, flags);
124 return -ENOMEM;
125 }
126 list_for_each_entry(this, &dev->local, entry)
127 memcpy(tmp_bufp++, &this->addr, sizeof(struct sockaddr_atmsvc));
128 spin_unlock_irqrestore(&dev->lock, flags);
129 error = total > size ? -E2BIG : total;
130 if (copy_to_user(buf, tmp_buf, total < size ? total : size))
131 error = -EFAULT;
132 kfree(tmp_buf);
133 return error;
134}
diff --git a/net/atm/addr.h b/net/atm/addr.h
new file mode 100644
index 000000000000..3099d21feeaa
--- /dev/null
+++ b/net/atm/addr.h
@@ -0,0 +1,18 @@
1/* net/atm/addr.h - Local ATM address registry */
2
3/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
4
5
6#ifndef NET_ATM_ADDR_H
7#define NET_ATM_ADDR_H
8
9#include <linux/atm.h>
10#include <linux/atmdev.h>
11
12
13void atm_reset_addr(struct atm_dev *dev);
14int atm_add_addr(struct atm_dev *dev,struct sockaddr_atmsvc *addr);
15int atm_del_addr(struct atm_dev *dev,struct sockaddr_atmsvc *addr);
16int atm_get_addr(struct atm_dev *dev,struct sockaddr_atmsvc __user *buf,size_t size);
17
18#endif
diff --git a/net/atm/atm_misc.c b/net/atm/atm_misc.c
new file mode 100644
index 000000000000..b2113c3454ae
--- /dev/null
+++ b/net/atm/atm_misc.c
@@ -0,0 +1,106 @@
1/* net/atm/atm_misc.c - Various functions for use by ATM drivers */
2
3/* Written 1995-2000 by Werner Almesberger, EPFL ICA */
4
5
6#include <linux/module.h>
7#include <linux/atm.h>
8#include <linux/atmdev.h>
9#include <linux/skbuff.h>
10#include <linux/sonet.h>
11#include <linux/bitops.h>
12#include <asm/atomic.h>
13#include <asm/errno.h>
14
15
16int atm_charge(struct atm_vcc *vcc,int truesize)
17{
18 atm_force_charge(vcc,truesize);
19 if (atomic_read(&sk_atm(vcc)->sk_rmem_alloc) <= sk_atm(vcc)->sk_rcvbuf)
20 return 1;
21 atm_return(vcc,truesize);
22 atomic_inc(&vcc->stats->rx_drop);
23 return 0;
24}
25
26
27struct sk_buff *atm_alloc_charge(struct atm_vcc *vcc,int pdu_size,
28 int gfp_flags)
29{
30 struct sock *sk = sk_atm(vcc);
31 int guess = atm_guess_pdu2truesize(pdu_size);
32
33 atm_force_charge(vcc,guess);
34 if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf) {
35 struct sk_buff *skb = alloc_skb(pdu_size,gfp_flags);
36
37 if (skb) {
38 atomic_add(skb->truesize-guess,
39 &sk->sk_rmem_alloc);
40 return skb;
41 }
42 }
43 atm_return(vcc,guess);
44 atomic_inc(&vcc->stats->rx_drop);
45 return NULL;
46}
47
48
49/*
50 * atm_pcr_goal returns the positive PCR if it should be rounded up, the
51 * negative PCR if it should be rounded down, and zero if the maximum available
52 * bandwidth should be used.
53 *
54 * The rules are as follows (* = maximum, - = absent (0), x = value "x",
55 * (x+ = x or next value above x, x- = x or next value below):
56 *
57 * min max pcr result min max pcr result
58 * - - - * (UBR only) x - - x+
59 * - - * * x - * *
60 * - - z z- x - z z-
61 * - * - * x * - x+
62 * - * * * x * * *
63 * - * z z- x * z z-
64 * - y - y- x y - x+
65 * - y * y- x y * y-
66 * - y z z- x y z z-
67 *
68 * All non-error cases can be converted with the following simple set of rules:
69 *
70 * if pcr == z then z-
71 * else if min == x && pcr == - then x+
72 * else if max == y then y-
73 * else *
74 */
75
76
77int atm_pcr_goal(struct atm_trafprm *tp)
78{
79 if (tp->pcr && tp->pcr != ATM_MAX_PCR) return -tp->pcr;
80 if (tp->min_pcr && !tp->pcr) return tp->min_pcr;
81 if (tp->max_pcr != ATM_MAX_PCR) return -tp->max_pcr;
82 return 0;
83}
84
85
86void sonet_copy_stats(struct k_sonet_stats *from,struct sonet_stats *to)
87{
88#define __HANDLE_ITEM(i) to->i = atomic_read(&from->i)
89 __SONET_ITEMS
90#undef __HANDLE_ITEM
91}
92
93
94void sonet_subtract_stats(struct k_sonet_stats *from,struct sonet_stats *to)
95{
96#define __HANDLE_ITEM(i) atomic_sub(to->i,&from->i)
97 __SONET_ITEMS
98#undef __HANDLE_ITEM
99}
100
101
102EXPORT_SYMBOL(atm_charge);
103EXPORT_SYMBOL(atm_alloc_charge);
104EXPORT_SYMBOL(atm_pcr_goal);
105EXPORT_SYMBOL(sonet_copy_stats);
106EXPORT_SYMBOL(sonet_subtract_stats);
diff --git a/net/atm/br2684.c b/net/atm/br2684.c
new file mode 100644
index 000000000000..e6954cf1459d
--- /dev/null
+++ b/net/atm/br2684.c
@@ -0,0 +1,824 @@
1/*
2Experimental ethernet netdevice using ATM AAL5 as underlying carrier
3(RFC1483 obsoleted by RFC2684) for Linux 2.4
4Author: Marcell GAL, 2000, XDSL Ltd, Hungary
5*/
6
7#include <linux/module.h>
8#include <linux/config.h>
9#include <linux/init.h>
10#include <linux/kernel.h>
11#include <linux/list.h>
12#include <linux/netdevice.h>
13#include <linux/skbuff.h>
14#include <linux/etherdevice.h>
15#include <linux/rtnetlink.h>
16#include <linux/ip.h>
17#include <asm/uaccess.h>
18#include <net/arp.h>
19#include <linux/atm.h>
20#include <linux/atmdev.h>
21#include <linux/seq_file.h>
22
23#include <linux/atmbr2684.h>
24
25#include "common.h"
26#include "ipcommon.h"
27
28/*
29 * Define this to use a version of the code which interacts with the higher
30 * layers in a more intellegent way, by always reserving enough space for
31 * our header at the begining of the packet. However, there may still be
32 * some problems with programs like tcpdump. In 2.5 we'll sort out what
33 * we need to do to get this perfect. For now we just will copy the packet
34 * if we need space for the header
35 */
36/* #define FASTER_VERSION */
37
38#ifdef DEBUG
39#define DPRINTK(format, args...) printk(KERN_DEBUG "br2684: " format, ##args)
40#else
41#define DPRINTK(format, args...)
42#endif
43
44#ifdef SKB_DEBUG
45static void skb_debug(const struct sk_buff *skb)
46{
47#define NUM2PRINT 50
48 char buf[NUM2PRINT * 3 + 1]; /* 3 chars per byte */
49 int i = 0;
50 for (i = 0; i < skb->len && i < NUM2PRINT; i++) {
51 sprintf(buf + i * 3, "%2.2x ", 0xff & skb->data[i]);
52 }
53 printk(KERN_DEBUG "br2684: skb: %s\n", buf);
54}
55#else
56#define skb_debug(skb) do {} while (0)
57#endif
58
59static unsigned char llc_oui_pid_pad[] =
60 { 0xAA, 0xAA, 0x03, 0x00, 0x80, 0xC2, 0x00, 0x07, 0x00, 0x00 };
61#define PADLEN (2)
62
63enum br2684_encaps {
64 e_vc = BR2684_ENCAPS_VC,
65 e_llc = BR2684_ENCAPS_LLC,
66};
67
68struct br2684_vcc {
69 struct atm_vcc *atmvcc;
70 struct net_device *device;
71 /* keep old push,pop functions for chaining */
72 void (*old_push)(struct atm_vcc *vcc,struct sk_buff *skb);
73 /* void (*old_pop)(struct atm_vcc *vcc,struct sk_buff *skb); */
74 enum br2684_encaps encaps;
75 struct list_head brvccs;
76#ifdef CONFIG_ATM_BR2684_IPFILTER
77 struct br2684_filter filter;
78#endif /* CONFIG_ATM_BR2684_IPFILTER */
79#ifndef FASTER_VERSION
80 unsigned copies_needed, copies_failed;
81#endif /* FASTER_VERSION */
82};
83
84struct br2684_dev {
85 struct net_device *net_dev;
86 struct list_head br2684_devs;
87 int number;
88 struct list_head brvccs; /* one device <=> one vcc (before xmas) */
89 struct net_device_stats stats;
90 int mac_was_set;
91};
92
93/*
94 * This lock should be held for writing any time the list of devices or
95 * their attached vcc's could be altered. It should be held for reading
96 * any time these are being queried. Note that we sometimes need to
97 * do read-locking under interrupt context, so write locking must block
98 * the current CPU's interrupts
99 */
100static DEFINE_RWLOCK(devs_lock);
101
102static LIST_HEAD(br2684_devs);
103
104static inline struct br2684_dev *BRPRIV(const struct net_device *net_dev)
105{
106 return (struct br2684_dev *) net_dev->priv;
107}
108
109static inline struct net_device *list_entry_brdev(const struct list_head *le)
110{
111 return list_entry(le, struct br2684_dev, br2684_devs)->net_dev;
112}
113
114static inline struct br2684_vcc *BR2684_VCC(const struct atm_vcc *atmvcc)
115{
116 return (struct br2684_vcc *) (atmvcc->user_back);
117}
118
119static inline struct br2684_vcc *list_entry_brvcc(const struct list_head *le)
120{
121 return list_entry(le, struct br2684_vcc, brvccs);
122}
123
124/* Caller should hold read_lock(&devs_lock) */
125static struct net_device *br2684_find_dev(const struct br2684_if_spec *s)
126{
127 struct list_head *lh;
128 struct net_device *net_dev;
129 switch (s->method) {
130 case BR2684_FIND_BYNUM:
131 list_for_each(lh, &br2684_devs) {
132 net_dev = list_entry_brdev(lh);
133 if (BRPRIV(net_dev)->number == s->spec.devnum)
134 return net_dev;
135 }
136 break;
137 case BR2684_FIND_BYIFNAME:
138 list_for_each(lh, &br2684_devs) {
139 net_dev = list_entry_brdev(lh);
140 if (!strncmp(net_dev->name, s->spec.ifname, IFNAMSIZ))
141 return net_dev;
142 }
143 break;
144 }
145 return NULL;
146}
147
148/*
149 * Send a packet out a particular vcc. Not to useful right now, but paves
150 * the way for multiple vcc's per itf. Returns true if we can send,
151 * otherwise false
152 */
153static int br2684_xmit_vcc(struct sk_buff *skb, struct br2684_dev *brdev,
154 struct br2684_vcc *brvcc)
155{
156 struct atm_vcc *atmvcc;
157#ifdef FASTER_VERSION
158 if (brvcc->encaps == e_llc)
159 memcpy(skb_push(skb, 8), llc_oui_pid_pad, 8);
160 /* last 2 bytes of llc_oui_pid_pad are managed by header routines;
161 yes, you got it: 8 + 2 = sizeof(llc_oui_pid_pad)
162 */
163#else
164 int minheadroom = (brvcc->encaps == e_llc) ? 10 : 2;
165 if (skb_headroom(skb) < minheadroom) {
166 struct sk_buff *skb2 = skb_realloc_headroom(skb, minheadroom);
167 brvcc->copies_needed++;
168 dev_kfree_skb(skb);
169 if (skb2 == NULL) {
170 brvcc->copies_failed++;
171 return 0;
172 }
173 skb = skb2;
174 }
175 skb_push(skb, minheadroom);
176 if (brvcc->encaps == e_llc)
177 memcpy(skb->data, llc_oui_pid_pad, 10);
178 else
179 memset(skb->data, 0, 2);
180#endif /* FASTER_VERSION */
181 skb_debug(skb);
182
183 ATM_SKB(skb)->vcc = atmvcc = brvcc->atmvcc;
184 DPRINTK("atm_skb(%p)->vcc(%p)->dev(%p)\n", skb, atmvcc, atmvcc->dev);
185 if (!atm_may_send(atmvcc, skb->truesize)) {
186 /* we free this here for now, because we cannot know in a higher
187 layer whether the skb point it supplied wasn't freed yet.
188 now, it always is.
189 */
190 dev_kfree_skb(skb);
191 return 0;
192 }
193 atomic_add(skb->truesize, &sk_atm(atmvcc)->sk_wmem_alloc);
194 ATM_SKB(skb)->atm_options = atmvcc->atm_options;
195 brdev->stats.tx_packets++;
196 brdev->stats.tx_bytes += skb->len;
197 atmvcc->send(atmvcc, skb);
198 return 1;
199}
200
201static inline struct br2684_vcc *pick_outgoing_vcc(struct sk_buff *skb,
202 struct br2684_dev *brdev)
203{
204 return list_empty(&brdev->brvccs) ? NULL :
205 list_entry_brvcc(brdev->brvccs.next); /* 1 vcc/dev right now */
206}
207
208static int br2684_start_xmit(struct sk_buff *skb, struct net_device *dev)
209{
210 struct br2684_dev *brdev = BRPRIV(dev);
211 struct br2684_vcc *brvcc;
212
213 DPRINTK("br2684_start_xmit, skb->dst=%p\n", skb->dst);
214 read_lock(&devs_lock);
215 brvcc = pick_outgoing_vcc(skb, brdev);
216 if (brvcc == NULL) {
217 DPRINTK("no vcc attached to dev %s\n", dev->name);
218 brdev->stats.tx_errors++;
219 brdev->stats.tx_carrier_errors++;
220 /* netif_stop_queue(dev); */
221 dev_kfree_skb(skb);
222 read_unlock(&devs_lock);
223 return -EUNATCH;
224 }
225 if (!br2684_xmit_vcc(skb, brdev, brvcc)) {
226 /*
227 * We should probably use netif_*_queue() here, but that
228 * involves added complication. We need to walk before
229 * we can run
230 */
231 /* don't free here! this pointer might be no longer valid!
232 dev_kfree_skb(skb);
233 */
234 brdev->stats.tx_errors++;
235 brdev->stats.tx_fifo_errors++;
236 }
237 read_unlock(&devs_lock);
238 return 0;
239}
240
241static struct net_device_stats *br2684_get_stats(struct net_device *dev)
242{
243 DPRINTK("br2684_get_stats\n");
244 return &BRPRIV(dev)->stats;
245}
246
247#ifdef FASTER_VERSION
248/*
249 * These mirror eth_header and eth_header_cache. They are not usually
250 * exported for use in modules, so we grab them from net_device
251 * after ether_setup() is done with it. Bit of a hack.
252 */
253static int (*my_eth_header)(struct sk_buff *, struct net_device *,
254 unsigned short, void *, void *, unsigned);
255static int (*my_eth_header_cache)(struct neighbour *, struct hh_cache *);
256
257static int
258br2684_header(struct sk_buff *skb, struct net_device *dev,
259 unsigned short type, void *daddr, void *saddr, unsigned len)
260{
261 u16 *pad_before_eth;
262 int t = my_eth_header(skb, dev, type, daddr, saddr, len);
263 if (t > 0) {
264 pad_before_eth = (u16 *) skb_push(skb, 2);
265 *pad_before_eth = 0;
266 return dev->hard_header_len; /* or return 16; ? */
267 } else
268 return t;
269}
270
271static int
272br2684_header_cache(struct neighbour *neigh, struct hh_cache *hh)
273{
274/* hh_data is 16 bytes long. if encaps is ether-llc we need 24, so
275xmit will add the additional header part in that case */
276 u16 *pad_before_eth = (u16 *)(hh->hh_data);
277 int t = my_eth_header_cache(neigh, hh);
278 DPRINTK("br2684_header_cache, neigh=%p, hh_cache=%p\n", neigh, hh);
279 if (t < 0)
280 return t;
281 else {
282 *pad_before_eth = 0;
283 hh->hh_len = PADLEN + ETH_HLEN;
284 }
285 return 0;
286}
287
288/*
289 * This is similar to eth_type_trans, which cannot be used because of
290 * our dev->hard_header_len
291 */
292static inline unsigned short br_type_trans(struct sk_buff *skb,
293 struct net_device *dev)
294{
295 struct ethhdr *eth;
296 unsigned char *rawp;
297 eth = eth_hdr(skb);
298
299 if (*eth->h_dest & 1) {
300 if (memcmp(eth->h_dest, dev->broadcast, ETH_ALEN) == 0)
301 skb->pkt_type = PACKET_BROADCAST;
302 else
303 skb->pkt_type = PACKET_MULTICAST;
304 }
305
306 else if (memcmp(eth->h_dest, dev->dev_addr, ETH_ALEN))
307 skb->pkt_type = PACKET_OTHERHOST;
308
309 if (ntohs(eth->h_proto) >= 1536)
310 return eth->h_proto;
311
312 rawp = skb->data;
313
314 /*
315 * This is a magic hack to spot IPX packets. Older Novell breaks
316 * the protocol design and runs IPX over 802.3 without an 802.2 LLC
317 * layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This
318 * won't work for fault tolerant netware but does for the rest.
319 */
320 if (*(unsigned short *) rawp == 0xFFFF)
321 return htons(ETH_P_802_3);
322
323 /*
324 * Real 802.2 LLC
325 */
326 return htons(ETH_P_802_2);
327}
328#endif /* FASTER_VERSION */
329
330/*
331 * We remember when the MAC gets set, so we don't override it later with
332 * the ESI of the ATM card of the first VC
333 */
334static int (*my_eth_mac_addr)(struct net_device *, void *);
335static int br2684_mac_addr(struct net_device *dev, void *p)
336{
337 int err = my_eth_mac_addr(dev, p);
338 if (!err)
339 BRPRIV(dev)->mac_was_set = 1;
340 return err;
341}
342
343#ifdef CONFIG_ATM_BR2684_IPFILTER
344/* this IOCTL is experimental. */
345static int br2684_setfilt(struct atm_vcc *atmvcc, void __user *arg)
346{
347 struct br2684_vcc *brvcc;
348 struct br2684_filter_set fs;
349
350 if (copy_from_user(&fs, arg, sizeof fs))
351 return -EFAULT;
352 if (fs.ifspec.method != BR2684_FIND_BYNOTHING) {
353 /*
354 * This is really a per-vcc thing, but we can also search
355 * by device
356 */
357 struct br2684_dev *brdev;
358 read_lock(&devs_lock);
359 brdev = BRPRIV(br2684_find_dev(&fs.ifspec));
360 if (brdev == NULL || list_empty(&brdev->brvccs) ||
361 brdev->brvccs.next != brdev->brvccs.prev) /* >1 VCC */
362 brvcc = NULL;
363 else
364 brvcc = list_entry_brvcc(brdev->brvccs.next);
365 read_unlock(&devs_lock);
366 if (brvcc == NULL)
367 return -ESRCH;
368 } else
369 brvcc = BR2684_VCC(atmvcc);
370 memcpy(&brvcc->filter, &fs.filter, sizeof(brvcc->filter));
371 return 0;
372}
373
374/* Returns 1 if packet should be dropped */
375static inline int
376packet_fails_filter(u16 type, struct br2684_vcc *brvcc, struct sk_buff *skb)
377{
378 if (brvcc->filter.netmask == 0)
379 return 0; /* no filter in place */
380 if (type == __constant_htons(ETH_P_IP) &&
381 (((struct iphdr *) (skb->data))->daddr & brvcc->filter.
382 netmask) == brvcc->filter.prefix)
383 return 0;
384 if (type == __constant_htons(ETH_P_ARP))
385 return 0;
386 /* TODO: we should probably filter ARPs too.. don't want to have
387 * them returning values that don't make sense, or is that ok?
388 */
389 return 1; /* drop */
390}
391#endif /* CONFIG_ATM_BR2684_IPFILTER */
392
393static void br2684_close_vcc(struct br2684_vcc *brvcc)
394{
395 DPRINTK("removing VCC %p from dev %p\n", brvcc, brvcc->device);
396 write_lock_irq(&devs_lock);
397 list_del(&brvcc->brvccs);
398 write_unlock_irq(&devs_lock);
399 brvcc->atmvcc->user_back = NULL; /* what about vcc->recvq ??? */
400 brvcc->old_push(brvcc->atmvcc, NULL); /* pass on the bad news */
401 kfree(brvcc);
402 module_put(THIS_MODULE);
403}
404
405/* when AAL5 PDU comes in: */
406static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb)
407{
408 struct br2684_vcc *brvcc = BR2684_VCC(atmvcc);
409 struct net_device *net_dev = brvcc->device;
410 struct br2684_dev *brdev = BRPRIV(net_dev);
411 int plen = sizeof(llc_oui_pid_pad) + ETH_HLEN;
412
413 DPRINTK("br2684_push\n");
414
415 if (unlikely(skb == NULL)) {
416 /* skb==NULL means VCC is being destroyed */
417 br2684_close_vcc(brvcc);
418 if (list_empty(&brdev->brvccs)) {
419 read_lock(&devs_lock);
420 list_del(&brdev->br2684_devs);
421 read_unlock(&devs_lock);
422 unregister_netdev(net_dev);
423 free_netdev(net_dev);
424 }
425 return;
426 }
427
428 skb_debug(skb);
429 atm_return(atmvcc, skb->truesize);
430 DPRINTK("skb from brdev %p\n", brdev);
431 if (brvcc->encaps == e_llc) {
432 /* let us waste some time for checking the encapsulation.
433 Note, that only 7 char is checked so frames with a valid FCS
434 are also accepted (but FCS is not checked of course) */
435 if (memcmp(skb->data, llc_oui_pid_pad, 7)) {
436 brdev->stats.rx_errors++;
437 dev_kfree_skb(skb);
438 return;
439 }
440
441 /* Strip FCS if present */
442 if (skb->len > 7 && skb->data[7] == 0x01)
443 __skb_trim(skb, skb->len - 4);
444 } else {
445 plen = PADLEN + ETH_HLEN; /* pad, dstmac,srcmac, ethtype */
446 /* first 2 chars should be 0 */
447 if (*((u16 *) (skb->data)) != 0) {
448 brdev->stats.rx_errors++;
449 dev_kfree_skb(skb);
450 return;
451 }
452 }
453 if (skb->len < plen) {
454 brdev->stats.rx_errors++;
455 dev_kfree_skb(skb); /* dev_ not needed? */
456 return;
457 }
458
459#ifdef FASTER_VERSION
460 /* FIXME: tcpdump shows that pointer to mac header is 2 bytes earlier,
461 than should be. What else should I set? */
462 skb_pull(skb, plen);
463 skb->mac.raw = ((char *) (skb->data)) - ETH_HLEN;
464 skb->pkt_type = PACKET_HOST;
465#ifdef CONFIG_BR2684_FAST_TRANS
466 skb->protocol = ((u16 *) skb->data)[-1];
467#else /* some protocols might require this: */
468 skb->protocol = br_type_trans(skb, net_dev);
469#endif /* CONFIG_BR2684_FAST_TRANS */
470#else
471 skb_pull(skb, plen - ETH_HLEN);
472 skb->protocol = eth_type_trans(skb, net_dev);
473#endif /* FASTER_VERSION */
474#ifdef CONFIG_ATM_BR2684_IPFILTER
475 if (unlikely(packet_fails_filter(skb->protocol, brvcc, skb))) {
476 brdev->stats.rx_dropped++;
477 dev_kfree_skb(skb);
478 return;
479 }
480#endif /* CONFIG_ATM_BR2684_IPFILTER */
481 skb->dev = net_dev;
482 ATM_SKB(skb)->vcc = atmvcc; /* needed ? */
483 DPRINTK("received packet's protocol: %x\n", ntohs(skb->protocol));
484 skb_debug(skb);
485 if (unlikely(!(net_dev->flags & IFF_UP))) {
486 /* sigh, interface is down */
487 brdev->stats.rx_dropped++;
488 dev_kfree_skb(skb);
489 return;
490 }
491 brdev->stats.rx_packets++;
492 brdev->stats.rx_bytes += skb->len;
493 memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data));
494 netif_rx(skb);
495}
496
497static int br2684_regvcc(struct atm_vcc *atmvcc, void __user *arg)
498{
499/* assign a vcc to a dev
500Note: we do not have explicit unassign, but look at _push()
501*/
502 int err;
503 struct br2684_vcc *brvcc;
504 struct sk_buff_head copy;
505 struct sk_buff *skb;
506 struct br2684_dev *brdev;
507 struct net_device *net_dev;
508 struct atm_backend_br2684 be;
509
510 if (copy_from_user(&be, arg, sizeof be))
511 return -EFAULT;
512 brvcc = kmalloc(sizeof(struct br2684_vcc), GFP_KERNEL);
513 if (!brvcc)
514 return -ENOMEM;
515 memset(brvcc, 0, sizeof(struct br2684_vcc));
516 write_lock_irq(&devs_lock);
517 net_dev = br2684_find_dev(&be.ifspec);
518 if (net_dev == NULL) {
519 printk(KERN_ERR
520 "br2684: tried to attach to non-existant device\n");
521 err = -ENXIO;
522 goto error;
523 }
524 brdev = BRPRIV(net_dev);
525 if (atmvcc->push == NULL) {
526 err = -EBADFD;
527 goto error;
528 }
529 if (!list_empty(&brdev->brvccs)) {
530 /* Only 1 VCC/dev right now */
531 err = -EEXIST;
532 goto error;
533 }
534 if (be.fcs_in != BR2684_FCSIN_NO || be.fcs_out != BR2684_FCSOUT_NO ||
535 be.fcs_auto || be.has_vpiid || be.send_padding || (be.encaps !=
536 BR2684_ENCAPS_VC && be.encaps != BR2684_ENCAPS_LLC) ||
537 be.min_size != 0) {
538 err = -EINVAL;
539 goto error;
540 }
541 DPRINTK("br2684_regvcc vcc=%p, encaps=%d, brvcc=%p\n", atmvcc, be.encaps,
542 brvcc);
543 if (list_empty(&brdev->brvccs) && !brdev->mac_was_set) {
544 unsigned char *esi = atmvcc->dev->esi;
545 if (esi[0] | esi[1] | esi[2] | esi[3] | esi[4] | esi[5])
546 memcpy(net_dev->dev_addr, esi, net_dev->addr_len);
547 else
548 net_dev->dev_addr[2] = 1;
549 }
550 list_add(&brvcc->brvccs, &brdev->brvccs);
551 write_unlock_irq(&devs_lock);
552 brvcc->device = net_dev;
553 brvcc->atmvcc = atmvcc;
554 atmvcc->user_back = brvcc;
555 brvcc->encaps = (enum br2684_encaps) be.encaps;
556 brvcc->old_push = atmvcc->push;
557 barrier();
558 atmvcc->push = br2684_push;
559 skb_queue_head_init(&copy);
560 skb_migrate(&sk_atm(atmvcc)->sk_receive_queue, &copy);
561 while ((skb = skb_dequeue(&copy)) != NULL) {
562 BRPRIV(skb->dev)->stats.rx_bytes -= skb->len;
563 BRPRIV(skb->dev)->stats.rx_packets--;
564 br2684_push(atmvcc, skb);
565 }
566 __module_get(THIS_MODULE);
567 return 0;
568 error:
569 write_unlock_irq(&devs_lock);
570 kfree(brvcc);
571 return err;
572}
573
574static void br2684_setup(struct net_device *netdev)
575{
576 struct br2684_dev *brdev = BRPRIV(netdev);
577
578 ether_setup(netdev);
579 brdev->net_dev = netdev;
580
581#ifdef FASTER_VERSION
582 my_eth_header = netdev->hard_header;
583 netdev->hard_header = br2684_header;
584 my_eth_header_cache = netdev->hard_header_cache;
585 netdev->hard_header_cache = br2684_header_cache;
586 netdev->hard_header_len = sizeof(llc_oui_pid_pad) + ETH_HLEN; /* 10 + 14 */
587#endif
588 my_eth_mac_addr = netdev->set_mac_address;
589 netdev->set_mac_address = br2684_mac_addr;
590 netdev->hard_start_xmit = br2684_start_xmit;
591 netdev->get_stats = br2684_get_stats;
592
593 INIT_LIST_HEAD(&brdev->brvccs);
594}
595
596static int br2684_create(void __user *arg)
597{
598 int err;
599 struct net_device *netdev;
600 struct br2684_dev *brdev;
601 struct atm_newif_br2684 ni;
602
603 DPRINTK("br2684_create\n");
604
605 if (copy_from_user(&ni, arg, sizeof ni)) {
606 return -EFAULT;
607 }
608 if (ni.media != BR2684_MEDIA_ETHERNET || ni.mtu != 1500) {
609 return -EINVAL;
610 }
611
612 netdev = alloc_netdev(sizeof(struct br2684_dev),
613 ni.ifname[0] ? ni.ifname : "nas%d",
614 br2684_setup);
615 if (!netdev)
616 return -ENOMEM;
617
618 brdev = BRPRIV(netdev);
619
620 DPRINTK("registered netdev %s\n", netdev->name);
621 /* open, stop, do_ioctl ? */
622 err = register_netdev(netdev);
623 if (err < 0) {
624 printk(KERN_ERR "br2684_create: register_netdev failed\n");
625 free_netdev(netdev);
626 return err;
627 }
628
629 write_lock_irq(&devs_lock);
630 brdev->number = list_empty(&br2684_devs) ? 1 :
631 BRPRIV(list_entry_brdev(br2684_devs.prev))->number + 1;
632 list_add_tail(&brdev->br2684_devs, &br2684_devs);
633 write_unlock_irq(&devs_lock);
634 return 0;
635}
636
637/*
638 * This handles ioctls actually performed on our vcc - we must return
639 * -ENOIOCTLCMD for any unrecognized ioctl
640 */
641static int br2684_ioctl(struct socket *sock, unsigned int cmd,
642 unsigned long arg)
643{
644 struct atm_vcc *atmvcc = ATM_SD(sock);
645 void __user *argp = (void __user *)arg;
646
647 int err;
648 switch(cmd) {
649 case ATM_SETBACKEND:
650 case ATM_NEWBACKENDIF: {
651 atm_backend_t b;
652 err = get_user(b, (atm_backend_t __user *) argp);
653 if (err)
654 return -EFAULT;
655 if (b != ATM_BACKEND_BR2684)
656 return -ENOIOCTLCMD;
657 if (!capable(CAP_NET_ADMIN))
658 return -EPERM;
659 if (cmd == ATM_SETBACKEND)
660 return br2684_regvcc(atmvcc, argp);
661 else
662 return br2684_create(argp);
663 }
664#ifdef CONFIG_ATM_BR2684_IPFILTER
665 case BR2684_SETFILT:
666 if (atmvcc->push != br2684_push)
667 return -ENOIOCTLCMD;
668 if (!capable(CAP_NET_ADMIN))
669 return -EPERM;
670 err = br2684_setfilt(atmvcc, argp);
671 return err;
672#endif /* CONFIG_ATM_BR2684_IPFILTER */
673 }
674 return -ENOIOCTLCMD;
675}
676
677static struct atm_ioctl br2684_ioctl_ops = {
678 .owner = THIS_MODULE,
679 .ioctl = br2684_ioctl,
680};
681
682
683#ifdef CONFIG_PROC_FS
684static void *br2684_seq_start(struct seq_file *seq, loff_t *pos)
685{
686 loff_t offs = 0;
687 struct br2684_dev *brd;
688
689 read_lock(&devs_lock);
690
691 list_for_each_entry(brd, &br2684_devs, br2684_devs) {
692 if (offs == *pos)
693 return brd;
694 ++offs;
695 }
696 return NULL;
697}
698
699static void *br2684_seq_next(struct seq_file *seq, void *v, loff_t *pos)
700{
701 struct br2684_dev *brd = v;
702
703 ++*pos;
704
705 brd = list_entry(brd->br2684_devs.next,
706 struct br2684_dev, br2684_devs);
707 return (&brd->br2684_devs != &br2684_devs) ? brd : NULL;
708}
709
710static void br2684_seq_stop(struct seq_file *seq, void *v)
711{
712 read_unlock(&devs_lock);
713}
714
715static int br2684_seq_show(struct seq_file *seq, void *v)
716{
717 const struct br2684_dev *brdev = v;
718 const struct net_device *net_dev = brdev->net_dev;
719 const struct br2684_vcc *brvcc;
720
721 seq_printf(seq, "dev %.16s: num=%d, mac=%02X:%02X:"
722 "%02X:%02X:%02X:%02X (%s)\n", net_dev->name,
723 brdev->number,
724 net_dev->dev_addr[0],
725 net_dev->dev_addr[1],
726 net_dev->dev_addr[2],
727 net_dev->dev_addr[3],
728 net_dev->dev_addr[4],
729 net_dev->dev_addr[5],
730 brdev->mac_was_set ? "set" : "auto");
731
732 list_for_each_entry(brvcc, &brdev->brvccs, brvccs) {
733 seq_printf(seq, " vcc %d.%d.%d: encaps=%s"
734#ifndef FASTER_VERSION
735 ", failed copies %u/%u"
736#endif /* FASTER_VERSION */
737 "\n", brvcc->atmvcc->dev->number,
738 brvcc->atmvcc->vpi, brvcc->atmvcc->vci,
739 (brvcc->encaps == e_llc) ? "LLC" : "VC"
740#ifndef FASTER_VERSION
741 , brvcc->copies_failed
742 , brvcc->copies_needed
743#endif /* FASTER_VERSION */
744 );
745#ifdef CONFIG_ATM_BR2684_IPFILTER
746#define b1(var, byte) ((u8 *) &brvcc->filter.var)[byte]
747#define bs(var) b1(var, 0), b1(var, 1), b1(var, 2), b1(var, 3)
748 if (brvcc->filter.netmask != 0)
749 seq_printf(seq, " filter=%d.%d.%d.%d/"
750 "%d.%d.%d.%d\n",
751 bs(prefix), bs(netmask));
752#undef bs
753#undef b1
754#endif /* CONFIG_ATM_BR2684_IPFILTER */
755 }
756 return 0;
757}
758
759static struct seq_operations br2684_seq_ops = {
760 .start = br2684_seq_start,
761 .next = br2684_seq_next,
762 .stop = br2684_seq_stop,
763 .show = br2684_seq_show,
764};
765
766static int br2684_proc_open(struct inode *inode, struct file *file)
767{
768 return seq_open(file, &br2684_seq_ops);
769}
770
771static struct file_operations br2684_proc_ops = {
772 .owner = THIS_MODULE,
773 .open = br2684_proc_open,
774 .read = seq_read,
775 .llseek = seq_lseek,
776 .release = seq_release,
777};
778
779extern struct proc_dir_entry *atm_proc_root; /* from proc.c */
780#endif
781
782static int __init br2684_init(void)
783{
784#ifdef CONFIG_PROC_FS
785 struct proc_dir_entry *p;
786 if ((p = create_proc_entry("br2684", 0, atm_proc_root)) == NULL)
787 return -ENOMEM;
788 p->proc_fops = &br2684_proc_ops;
789#endif
790 register_atm_ioctl(&br2684_ioctl_ops);
791 return 0;
792}
793
794static void __exit br2684_exit(void)
795{
796 struct net_device *net_dev;
797 struct br2684_dev *brdev;
798 struct br2684_vcc *brvcc;
799 deregister_atm_ioctl(&br2684_ioctl_ops);
800
801#ifdef CONFIG_PROC_FS
802 remove_proc_entry("br2684", atm_proc_root);
803#endif
804
805 while (!list_empty(&br2684_devs)) {
806 net_dev = list_entry_brdev(br2684_devs.next);
807 brdev = BRPRIV(net_dev);
808 while (!list_empty(&brdev->brvccs)) {
809 brvcc = list_entry_brvcc(brdev->brvccs.next);
810 br2684_close_vcc(brvcc);
811 }
812
813 list_del(&brdev->br2684_devs);
814 unregister_netdev(net_dev);
815 free_netdev(net_dev);
816 }
817}
818
819module_init(br2684_init);
820module_exit(br2684_exit);
821
822MODULE_AUTHOR("Marcell GAL");
823MODULE_DESCRIPTION("RFC2684 bridged protocols over ATM/AAL5");
824MODULE_LICENSE("GPL");
diff --git a/net/atm/clip.c b/net/atm/clip.c
new file mode 100644
index 000000000000..28dab55a4387
--- /dev/null
+++ b/net/atm/clip.c
@@ -0,0 +1,1045 @@
1/* net/atm/clip.c - RFC1577 Classical IP over ATM */
2
3/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
4
5
6#include <linux/config.h>
7#include <linux/string.h>
8#include <linux/errno.h>
9#include <linux/kernel.h> /* for UINT_MAX */
10#include <linux/module.h>
11#include <linux/init.h>
12#include <linux/netdevice.h>
13#include <linux/skbuff.h>
14#include <linux/wait.h>
15#include <linux/timer.h>
16#include <linux/if_arp.h> /* for some manifest constants */
17#include <linux/notifier.h>
18#include <linux/atm.h>
19#include <linux/atmdev.h>
20#include <linux/atmclip.h>
21#include <linux/atmarp.h>
22#include <linux/ip.h> /* for net/route.h */
23#include <linux/in.h> /* for struct sockaddr_in */
24#include <linux/if.h> /* for IFF_UP */
25#include <linux/inetdevice.h>
26#include <linux/bitops.h>
27#include <linux/proc_fs.h>
28#include <linux/seq_file.h>
29#include <linux/rcupdate.h>
30#include <linux/jhash.h>
31#include <net/route.h> /* for struct rtable and routing */
32#include <net/icmp.h> /* icmp_send */
33#include <asm/param.h> /* for HZ */
34#include <asm/byteorder.h> /* for htons etc. */
35#include <asm/system.h> /* save/restore_flags */
36#include <asm/uaccess.h>
37#include <asm/atomic.h>
38
39#include "common.h"
40#include "resources.h"
41#include "ipcommon.h"
42#include <net/atmclip.h>
43
44
45#if 0
46#define DPRINTK(format,args...) printk(format,##args)
47#else
48#define DPRINTK(format,args...)
49#endif
50
51
52static struct net_device *clip_devs;
53static struct atm_vcc *atmarpd;
54static struct neigh_table clip_tbl;
55static struct timer_list idle_timer;
56static int start_timer = 1;
57
58
59static int to_atmarpd(enum atmarp_ctrl_type type,int itf,unsigned long ip)
60{
61 struct sock *sk;
62 struct atmarp_ctrl *ctrl;
63 struct sk_buff *skb;
64
65 DPRINTK("to_atmarpd(%d)\n",type);
66 if (!atmarpd) return -EUNATCH;
67 skb = alloc_skb(sizeof(struct atmarp_ctrl),GFP_ATOMIC);
68 if (!skb) return -ENOMEM;
69 ctrl = (struct atmarp_ctrl *) skb_put(skb,sizeof(struct atmarp_ctrl));
70 ctrl->type = type;
71 ctrl->itf_num = itf;
72 ctrl->ip = ip;
73 atm_force_charge(atmarpd,skb->truesize);
74
75 sk = sk_atm(atmarpd);
76 skb_queue_tail(&sk->sk_receive_queue, skb);
77 sk->sk_data_ready(sk, skb->len);
78 return 0;
79}
80
81
82static void link_vcc(struct clip_vcc *clip_vcc,struct atmarp_entry *entry)
83{
84 DPRINTK("link_vcc %p to entry %p (neigh %p)\n",clip_vcc,entry,
85 entry->neigh);
86 clip_vcc->entry = entry;
87 clip_vcc->xoff = 0; /* @@@ may overrun buffer by one packet */
88 clip_vcc->next = entry->vccs;
89 entry->vccs = clip_vcc;
90 entry->neigh->used = jiffies;
91}
92
93
94static void unlink_clip_vcc(struct clip_vcc *clip_vcc)
95{
96 struct atmarp_entry *entry = clip_vcc->entry;
97 struct clip_vcc **walk;
98
99 if (!entry) {
100 printk(KERN_CRIT "!clip_vcc->entry (clip_vcc %p)\n",clip_vcc);
101 return;
102 }
103 spin_lock_bh(&entry->neigh->dev->xmit_lock); /* block clip_start_xmit() */
104 entry->neigh->used = jiffies;
105 for (walk = &entry->vccs; *walk; walk = &(*walk)->next)
106 if (*walk == clip_vcc) {
107 int error;
108
109 *walk = clip_vcc->next; /* atomic */
110 clip_vcc->entry = NULL;
111 if (clip_vcc->xoff)
112 netif_wake_queue(entry->neigh->dev);
113 if (entry->vccs)
114 goto out;
115 entry->expires = jiffies-1;
116 /* force resolution or expiration */
117 error = neigh_update(entry->neigh, NULL, NUD_NONE,
118 NEIGH_UPDATE_F_ADMIN);
119 if (error)
120 printk(KERN_CRIT "unlink_clip_vcc: "
121 "neigh_update failed with %d\n",error);
122 goto out;
123 }
124 printk(KERN_CRIT "ATMARP: unlink_clip_vcc failed (entry %p, vcc "
125 "0x%p)\n",entry,clip_vcc);
126out:
127 spin_unlock_bh(&entry->neigh->dev->xmit_lock);
128}
129
130/* The neighbour entry n->lock is held. */
131static int neigh_check_cb(struct neighbour *n)
132{
133 struct atmarp_entry *entry = NEIGH2ENTRY(n);
134 struct clip_vcc *cv;
135
136 for (cv = entry->vccs; cv; cv = cv->next) {
137 unsigned long exp = cv->last_use + cv->idle_timeout;
138
139 if (cv->idle_timeout && time_after(jiffies, exp)) {
140 DPRINTK("releasing vcc %p->%p of entry %p\n",
141 cv, cv->vcc, entry);
142 vcc_release_async(cv->vcc, -ETIMEDOUT);
143 }
144 }
145
146 if (entry->vccs || time_before(jiffies, entry->expires))
147 return 0;
148
149 if (atomic_read(&n->refcnt) > 1) {
150 struct sk_buff *skb;
151
152 DPRINTK("destruction postponed with ref %d\n",
153 atomic_read(&n->refcnt));
154
155 while ((skb = skb_dequeue(&n->arp_queue)) != NULL)
156 dev_kfree_skb(skb);
157
158 return 0;
159 }
160
161 DPRINTK("expired neigh %p\n",n);
162 return 1;
163}
164
165static void idle_timer_check(unsigned long dummy)
166{
167 write_lock(&clip_tbl.lock);
168 __neigh_for_each_release(&clip_tbl, neigh_check_cb);
169 mod_timer(&idle_timer, jiffies+CLIP_CHECK_INTERVAL*HZ);
170 write_unlock(&clip_tbl.lock);
171}
172
173static int clip_arp_rcv(struct sk_buff *skb)
174{
175 struct atm_vcc *vcc;
176
177 DPRINTK("clip_arp_rcv\n");
178 vcc = ATM_SKB(skb)->vcc;
179 if (!vcc || !atm_charge(vcc,skb->truesize)) {
180 dev_kfree_skb_any(skb);
181 return 0;
182 }
183 DPRINTK("pushing to %p\n",vcc);
184 DPRINTK("using %p\n",CLIP_VCC(vcc)->old_push);
185 CLIP_VCC(vcc)->old_push(vcc,skb);
186 return 0;
187}
188
189static const unsigned char llc_oui[] = {
190 0xaa, /* DSAP: non-ISO */
191 0xaa, /* SSAP: non-ISO */
192 0x03, /* Ctrl: Unnumbered Information Command PDU */
193 0x00, /* OUI: EtherType */
194 0x00,
195 0x00 };
196
197static void clip_push(struct atm_vcc *vcc,struct sk_buff *skb)
198{
199 struct clip_vcc *clip_vcc = CLIP_VCC(vcc);
200
201 DPRINTK("clip push\n");
202 if (!skb) {
203 DPRINTK("removing VCC %p\n",clip_vcc);
204 if (clip_vcc->entry) unlink_clip_vcc(clip_vcc);
205 clip_vcc->old_push(vcc,NULL); /* pass on the bad news */
206 kfree(clip_vcc);
207 return;
208 }
209 atm_return(vcc,skb->truesize);
210 skb->dev = clip_vcc->entry ? clip_vcc->entry->neigh->dev : clip_devs;
211 /* clip_vcc->entry == NULL if we don't have an IP address yet */
212 if (!skb->dev) {
213 dev_kfree_skb_any(skb);
214 return;
215 }
216 ATM_SKB(skb)->vcc = vcc;
217 skb->mac.raw = skb->data;
218 if (!clip_vcc->encap || skb->len < RFC1483LLC_LEN || memcmp(skb->data,
219 llc_oui,sizeof(llc_oui))) skb->protocol = htons(ETH_P_IP);
220 else {
221 skb->protocol = ((u16 *) skb->data)[3];
222 skb_pull(skb,RFC1483LLC_LEN);
223 if (skb->protocol == htons(ETH_P_ARP)) {
224 PRIV(skb->dev)->stats.rx_packets++;
225 PRIV(skb->dev)->stats.rx_bytes += skb->len;
226 clip_arp_rcv(skb);
227 return;
228 }
229 }
230 clip_vcc->last_use = jiffies;
231 PRIV(skb->dev)->stats.rx_packets++;
232 PRIV(skb->dev)->stats.rx_bytes += skb->len;
233 memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data));
234 netif_rx(skb);
235}
236
237
238/*
239 * Note: these spinlocks _must_not_ block on non-SMP. The only goal is that
240 * clip_pop is atomic with respect to the critical section in clip_start_xmit.
241 */
242
243
244static void clip_pop(struct atm_vcc *vcc,struct sk_buff *skb)
245{
246 struct clip_vcc *clip_vcc = CLIP_VCC(vcc);
247 struct net_device *dev = skb->dev;
248 int old;
249 unsigned long flags;
250
251 DPRINTK("clip_pop(vcc %p)\n",vcc);
252 clip_vcc->old_pop(vcc,skb);
253 /* skb->dev == NULL in outbound ARP packets */
254 if (!dev) return;
255 spin_lock_irqsave(&PRIV(dev)->xoff_lock,flags);
256 if (atm_may_send(vcc,0)) {
257 old = xchg(&clip_vcc->xoff,0);
258 if (old) netif_wake_queue(dev);
259 }
260 spin_unlock_irqrestore(&PRIV(dev)->xoff_lock,flags);
261}
262
263
264static void clip_neigh_destroy(struct neighbour *neigh)
265{
266 DPRINTK("clip_neigh_destroy (neigh %p)\n",neigh);
267 if (NEIGH2ENTRY(neigh)->vccs)
268 printk(KERN_CRIT "clip_neigh_destroy: vccs != NULL !!!\n");
269 NEIGH2ENTRY(neigh)->vccs = (void *) 0xdeadbeef;
270}
271
272
273static void clip_neigh_solicit(struct neighbour *neigh,struct sk_buff *skb)
274{
275 DPRINTK("clip_neigh_solicit (neigh %p, skb %p)\n",neigh,skb);
276 to_atmarpd(act_need,PRIV(neigh->dev)->number,NEIGH2ENTRY(neigh)->ip);
277}
278
279
280static void clip_neigh_error(struct neighbour *neigh,struct sk_buff *skb)
281{
282#ifndef CONFIG_ATM_CLIP_NO_ICMP
283 icmp_send(skb,ICMP_DEST_UNREACH,ICMP_HOST_UNREACH,0);
284#endif
285 kfree_skb(skb);
286}
287
288
289static struct neigh_ops clip_neigh_ops = {
290 .family = AF_INET,
291 .destructor = clip_neigh_destroy,
292 .solicit = clip_neigh_solicit,
293 .error_report = clip_neigh_error,
294 .output = dev_queue_xmit,
295 .connected_output = dev_queue_xmit,
296 .hh_output = dev_queue_xmit,
297 .queue_xmit = dev_queue_xmit,
298};
299
300
301static int clip_constructor(struct neighbour *neigh)
302{
303 struct atmarp_entry *entry = NEIGH2ENTRY(neigh);
304 struct net_device *dev = neigh->dev;
305 struct in_device *in_dev;
306 struct neigh_parms *parms;
307
308 DPRINTK("clip_constructor (neigh %p, entry %p)\n",neigh,entry);
309 neigh->type = inet_addr_type(entry->ip);
310 if (neigh->type != RTN_UNICAST) return -EINVAL;
311
312 rcu_read_lock();
313 in_dev = rcu_dereference(__in_dev_get(dev));
314 if (!in_dev) {
315 rcu_read_unlock();
316 return -EINVAL;
317 }
318
319 parms = in_dev->arp_parms;
320 __neigh_parms_put(neigh->parms);
321 neigh->parms = neigh_parms_clone(parms);
322 rcu_read_unlock();
323
324 neigh->ops = &clip_neigh_ops;
325 neigh->output = neigh->nud_state & NUD_VALID ?
326 neigh->ops->connected_output : neigh->ops->output;
327 entry->neigh = neigh;
328 entry->vccs = NULL;
329 entry->expires = jiffies-1;
330 return 0;
331}
332
333static u32 clip_hash(const void *pkey, const struct net_device *dev)
334{
335 return jhash_2words(*(u32 *)pkey, dev->ifindex, clip_tbl.hash_rnd);
336}
337
338static struct neigh_table clip_tbl = {
339 .family = AF_INET,
340 .entry_size = sizeof(struct neighbour)+sizeof(struct atmarp_entry),
341 .key_len = 4,
342 .hash = clip_hash,
343 .constructor = clip_constructor,
344 .id = "clip_arp_cache",
345
346 /* parameters are copied from ARP ... */
347 .parms = {
348 .tbl = &clip_tbl,
349 .base_reachable_time = 30 * HZ,
350 .retrans_time = 1 * HZ,
351 .gc_staletime = 60 * HZ,
352 .reachable_time = 30 * HZ,
353 .delay_probe_time = 5 * HZ,
354 .queue_len = 3,
355 .ucast_probes = 3,
356 .mcast_probes = 3,
357 .anycast_delay = 1 * HZ,
358 .proxy_delay = (8 * HZ) / 10,
359 .proxy_qlen = 64,
360 .locktime = 1 * HZ,
361 },
362 .gc_interval = 30 * HZ,
363 .gc_thresh1 = 128,
364 .gc_thresh2 = 512,
365 .gc_thresh3 = 1024,
366};
367
368
369/* @@@ copy bh locking from arp.c -- need to bh-enable atm code before */
370
371/*
372 * We play with the resolve flag: 0 and 1 have the usual meaning, but -1 means
373 * to allocate the neighbour entry but not to ask atmarpd for resolution. Also,
374 * don't increment the usage count. This is used to create entries in
375 * clip_setentry.
376 */
377
378
379static int clip_encap(struct atm_vcc *vcc,int mode)
380{
381 CLIP_VCC(vcc)->encap = mode;
382 return 0;
383}
384
385
386static int clip_start_xmit(struct sk_buff *skb,struct net_device *dev)
387{
388 struct clip_priv *clip_priv = PRIV(dev);
389 struct atmarp_entry *entry;
390 struct atm_vcc *vcc;
391 int old;
392 unsigned long flags;
393
394 DPRINTK("clip_start_xmit (skb %p)\n",skb);
395 if (!skb->dst) {
396 printk(KERN_ERR "clip_start_xmit: skb->dst == NULL\n");
397 dev_kfree_skb(skb);
398 clip_priv->stats.tx_dropped++;
399 return 0;
400 }
401 if (!skb->dst->neighbour) {
402#if 0
403 skb->dst->neighbour = clip_find_neighbour(skb->dst,1);
404 if (!skb->dst->neighbour) {
405 dev_kfree_skb(skb); /* lost that one */
406 clip_priv->stats.tx_dropped++;
407 return 0;
408 }
409#endif
410 printk(KERN_ERR "clip_start_xmit: NO NEIGHBOUR !\n");
411 dev_kfree_skb(skb);
412 clip_priv->stats.tx_dropped++;
413 return 0;
414 }
415 entry = NEIGH2ENTRY(skb->dst->neighbour);
416 if (!entry->vccs) {
417 if (time_after(jiffies, entry->expires)) {
418 /* should be resolved */
419 entry->expires = jiffies+ATMARP_RETRY_DELAY*HZ;
420 to_atmarpd(act_need,PRIV(dev)->number,entry->ip);
421 }
422 if (entry->neigh->arp_queue.qlen < ATMARP_MAX_UNRES_PACKETS)
423 skb_queue_tail(&entry->neigh->arp_queue,skb);
424 else {
425 dev_kfree_skb(skb);
426 clip_priv->stats.tx_dropped++;
427 }
428 return 0;
429 }
430 DPRINTK("neigh %p, vccs %p\n",entry,entry->vccs);
431 ATM_SKB(skb)->vcc = vcc = entry->vccs->vcc;
432 DPRINTK("using neighbour %p, vcc %p\n",skb->dst->neighbour,vcc);
433 if (entry->vccs->encap) {
434 void *here;
435
436 here = skb_push(skb,RFC1483LLC_LEN);
437 memcpy(here,llc_oui,sizeof(llc_oui));
438 ((u16 *) here)[3] = skb->protocol;
439 }
440 atomic_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
441 ATM_SKB(skb)->atm_options = vcc->atm_options;
442 entry->vccs->last_use = jiffies;
443 DPRINTK("atm_skb(%p)->vcc(%p)->dev(%p)\n",skb,vcc,vcc->dev);
444 old = xchg(&entry->vccs->xoff,1); /* assume XOFF ... */
445 if (old) {
446 printk(KERN_WARNING "clip_start_xmit: XOFF->XOFF transition\n");
447 return 0;
448 }
449 clip_priv->stats.tx_packets++;
450 clip_priv->stats.tx_bytes += skb->len;
451 (void) vcc->send(vcc,skb);
452 if (atm_may_send(vcc,0)) {
453 entry->vccs->xoff = 0;
454 return 0;
455 }
456 spin_lock_irqsave(&clip_priv->xoff_lock,flags);
457 netif_stop_queue(dev); /* XOFF -> throttle immediately */
458 barrier();
459 if (!entry->vccs->xoff)
460 netif_start_queue(dev);
461 /* Oh, we just raced with clip_pop. netif_start_queue should be
462 good enough, because nothing should really be asleep because
463 of the brief netif_stop_queue. If this isn't true or if it
464 changes, use netif_wake_queue instead. */
465 spin_unlock_irqrestore(&clip_priv->xoff_lock,flags);
466 return 0;
467}
468
469
470static struct net_device_stats *clip_get_stats(struct net_device *dev)
471{
472 return &PRIV(dev)->stats;
473}
474
475
476static int clip_mkip(struct atm_vcc *vcc,int timeout)
477{
478 struct clip_vcc *clip_vcc;
479 struct sk_buff_head copy;
480 struct sk_buff *skb;
481
482 if (!vcc->push) return -EBADFD;
483 clip_vcc = kmalloc(sizeof(struct clip_vcc),GFP_KERNEL);
484 if (!clip_vcc) return -ENOMEM;
485 DPRINTK("mkip clip_vcc %p vcc %p\n",clip_vcc,vcc);
486 clip_vcc->vcc = vcc;
487 vcc->user_back = clip_vcc;
488 set_bit(ATM_VF_IS_CLIP, &vcc->flags);
489 clip_vcc->entry = NULL;
490 clip_vcc->xoff = 0;
491 clip_vcc->encap = 1;
492 clip_vcc->last_use = jiffies;
493 clip_vcc->idle_timeout = timeout*HZ;
494 clip_vcc->old_push = vcc->push;
495 clip_vcc->old_pop = vcc->pop;
496 vcc->push = clip_push;
497 vcc->pop = clip_pop;
498 skb_queue_head_init(&copy);
499 skb_migrate(&sk_atm(vcc)->sk_receive_queue, &copy);
500 /* re-process everything received between connection setup and MKIP */
501 while ((skb = skb_dequeue(&copy)) != NULL)
502 if (!clip_devs) {
503 atm_return(vcc,skb->truesize);
504 kfree_skb(skb);
505 }
506 else {
507 unsigned int len = skb->len;
508
509 clip_push(vcc,skb);
510 PRIV(skb->dev)->stats.rx_packets--;
511 PRIV(skb->dev)->stats.rx_bytes -= len;
512 }
513 return 0;
514}
515
516
517static int clip_setentry(struct atm_vcc *vcc,u32 ip)
518{
519 struct neighbour *neigh;
520 struct atmarp_entry *entry;
521 int error;
522 struct clip_vcc *clip_vcc;
523 struct flowi fl = { .nl_u = { .ip4_u = { .daddr = ip, .tos = 1 } } };
524 struct rtable *rt;
525
526 if (vcc->push != clip_push) {
527 printk(KERN_WARNING "clip_setentry: non-CLIP VCC\n");
528 return -EBADF;
529 }
530 clip_vcc = CLIP_VCC(vcc);
531 if (!ip) {
532 if (!clip_vcc->entry) {
533 printk(KERN_ERR "hiding hidden ATMARP entry\n");
534 return 0;
535 }
536 DPRINTK("setentry: remove\n");
537 unlink_clip_vcc(clip_vcc);
538 return 0;
539 }
540 error = ip_route_output_key(&rt,&fl);
541 if (error) return error;
542 neigh = __neigh_lookup(&clip_tbl,&ip,rt->u.dst.dev,1);
543 ip_rt_put(rt);
544 if (!neigh)
545 return -ENOMEM;
546 entry = NEIGH2ENTRY(neigh);
547 if (entry != clip_vcc->entry) {
548 if (!clip_vcc->entry) DPRINTK("setentry: add\n");
549 else {
550 DPRINTK("setentry: update\n");
551 unlink_clip_vcc(clip_vcc);
552 }
553 link_vcc(clip_vcc,entry);
554 }
555 error = neigh_update(neigh, llc_oui, NUD_PERMANENT,
556 NEIGH_UPDATE_F_OVERRIDE|NEIGH_UPDATE_F_ADMIN);
557 neigh_release(neigh);
558 return error;
559}
560
561
562static void clip_setup(struct net_device *dev)
563{
564 dev->hard_start_xmit = clip_start_xmit;
565 /* sg_xmit ... */
566 dev->get_stats = clip_get_stats;
567 dev->type = ARPHRD_ATM;
568 dev->hard_header_len = RFC1483LLC_LEN;
569 dev->mtu = RFC1626_MTU;
570 dev->tx_queue_len = 100; /* "normal" queue (packets) */
571 /* When using a "real" qdisc, the qdisc determines the queue */
572 /* length. tx_queue_len is only used for the default case, */
573 /* without any more elaborate queuing. 100 is a reasonable */
574 /* compromise between decent burst-tolerance and protection */
575 /* against memory hogs. */
576}
577
578
579static int clip_create(int number)
580{
581 struct net_device *dev;
582 struct clip_priv *clip_priv;
583 int error;
584
585 if (number != -1) {
586 for (dev = clip_devs; dev; dev = PRIV(dev)->next)
587 if (PRIV(dev)->number == number) return -EEXIST;
588 }
589 else {
590 number = 0;
591 for (dev = clip_devs; dev; dev = PRIV(dev)->next)
592 if (PRIV(dev)->number >= number)
593 number = PRIV(dev)->number+1;
594 }
595 dev = alloc_netdev(sizeof(struct clip_priv), "", clip_setup);
596 if (!dev)
597 return -ENOMEM;
598 clip_priv = PRIV(dev);
599 sprintf(dev->name,"atm%d",number);
600 spin_lock_init(&clip_priv->xoff_lock);
601 clip_priv->number = number;
602 error = register_netdev(dev);
603 if (error) {
604 free_netdev(dev);
605 return error;
606 }
607 clip_priv->next = clip_devs;
608 clip_devs = dev;
609 DPRINTK("registered (net:%s)\n",dev->name);
610 return number;
611}
612
613
614static int clip_device_event(struct notifier_block *this,unsigned long event,
615 void *dev)
616{
617 /* ignore non-CLIP devices */
618 if (((struct net_device *) dev)->type != ARPHRD_ATM ||
619 ((struct net_device *) dev)->hard_start_xmit != clip_start_xmit)
620 return NOTIFY_DONE;
621 switch (event) {
622 case NETDEV_UP:
623 DPRINTK("clip_device_event NETDEV_UP\n");
624 (void) to_atmarpd(act_up,PRIV(dev)->number,0);
625 break;
626 case NETDEV_GOING_DOWN:
627 DPRINTK("clip_device_event NETDEV_DOWN\n");
628 (void) to_atmarpd(act_down,PRIV(dev)->number,0);
629 break;
630 case NETDEV_CHANGE:
631 case NETDEV_CHANGEMTU:
632 DPRINTK("clip_device_event NETDEV_CHANGE*\n");
633 (void) to_atmarpd(act_change,PRIV(dev)->number,0);
634 break;
635 case NETDEV_REBOOT:
636 case NETDEV_REGISTER:
637 case NETDEV_DOWN:
638 DPRINTK("clip_device_event %ld\n",event);
639 /* ignore */
640 break;
641 default:
642 printk(KERN_WARNING "clip_device_event: unknown event "
643 "%ld\n",event);
644 break;
645 }
646 return NOTIFY_DONE;
647}
648
649
650static int clip_inet_event(struct notifier_block *this,unsigned long event,
651 void *ifa)
652{
653 struct in_device *in_dev;
654
655 in_dev = ((struct in_ifaddr *) ifa)->ifa_dev;
656 if (!in_dev || !in_dev->dev) {
657 printk(KERN_WARNING "clip_inet_event: no device\n");
658 return NOTIFY_DONE;
659 }
660 /*
661 * Transitions are of the down-change-up type, so it's sufficient to
662 * handle the change on up.
663 */
664 if (event != NETDEV_UP) return NOTIFY_DONE;
665 return clip_device_event(this,NETDEV_CHANGE,in_dev->dev);
666}
667
668
669static struct notifier_block clip_dev_notifier = {
670 clip_device_event,
671 NULL,
672 0
673};
674
675
676
677static struct notifier_block clip_inet_notifier = {
678 clip_inet_event,
679 NULL,
680 0
681};
682
683
684
685static void atmarpd_close(struct atm_vcc *vcc)
686{
687 DPRINTK("atmarpd_close\n");
688 atmarpd = NULL; /* assumed to be atomic */
689 barrier();
690 unregister_inetaddr_notifier(&clip_inet_notifier);
691 unregister_netdevice_notifier(&clip_dev_notifier);
692 if (skb_peek(&sk_atm(vcc)->sk_receive_queue))
693 printk(KERN_ERR "atmarpd_close: closing with requests "
694 "pending\n");
695 skb_queue_purge(&sk_atm(vcc)->sk_receive_queue);
696 DPRINTK("(done)\n");
697 module_put(THIS_MODULE);
698}
699
700
701static struct atmdev_ops atmarpd_dev_ops = {
702 .close = atmarpd_close
703};
704
705
706static struct atm_dev atmarpd_dev = {
707 .ops = &atmarpd_dev_ops,
708 .type = "arpd",
709 .number = 999,
710 .lock = SPIN_LOCK_UNLOCKED
711};
712
713
714static int atm_init_atmarp(struct atm_vcc *vcc)
715{
716 if (atmarpd) return -EADDRINUSE;
717 if (start_timer) {
718 start_timer = 0;
719 init_timer(&idle_timer);
720 idle_timer.expires = jiffies+CLIP_CHECK_INTERVAL*HZ;
721 idle_timer.function = idle_timer_check;
722 add_timer(&idle_timer);
723 }
724 atmarpd = vcc;
725 set_bit(ATM_VF_META,&vcc->flags);
726 set_bit(ATM_VF_READY,&vcc->flags);
727 /* allow replies and avoid getting closed if signaling dies */
728 vcc->dev = &atmarpd_dev;
729 vcc_insert_socket(sk_atm(vcc));
730 vcc->push = NULL;
731 vcc->pop = NULL; /* crash */
732 vcc->push_oam = NULL; /* crash */
733 if (register_netdevice_notifier(&clip_dev_notifier))
734 printk(KERN_ERR "register_netdevice_notifier failed\n");
735 if (register_inetaddr_notifier(&clip_inet_notifier))
736 printk(KERN_ERR "register_inetaddr_notifier failed\n");
737 return 0;
738}
739
740static int clip_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
741{
742 struct atm_vcc *vcc = ATM_SD(sock);
743 int err = 0;
744
745 switch (cmd) {
746 case SIOCMKCLIP:
747 case ATMARPD_CTRL:
748 case ATMARP_MKIP:
749 case ATMARP_SETENTRY:
750 case ATMARP_ENCAP:
751 if (!capable(CAP_NET_ADMIN))
752 return -EPERM;
753 break;
754 default:
755 return -ENOIOCTLCMD;
756 }
757
758 switch (cmd) {
759 case SIOCMKCLIP:
760 err = clip_create(arg);
761 break;
762 case ATMARPD_CTRL:
763 err = atm_init_atmarp(vcc);
764 if (!err) {
765 sock->state = SS_CONNECTED;
766 __module_get(THIS_MODULE);
767 }
768 break;
769 case ATMARP_MKIP:
770 err = clip_mkip(vcc ,arg);
771 break;
772 case ATMARP_SETENTRY:
773 err = clip_setentry(vcc, arg);
774 break;
775 case ATMARP_ENCAP:
776 err = clip_encap(vcc, arg);
777 break;
778 }
779 return err;
780}
781
782static struct atm_ioctl clip_ioctl_ops = {
783 .owner = THIS_MODULE,
784 .ioctl = clip_ioctl,
785};
786
787#ifdef CONFIG_PROC_FS
788
789static void svc_addr(struct seq_file *seq, struct sockaddr_atmsvc *addr)
790{
791 static int code[] = { 1,2,10,6,1,0 };
792 static int e164[] = { 1,8,4,6,1,0 };
793
794 if (*addr->sas_addr.pub) {
795 seq_printf(seq, "%s", addr->sas_addr.pub);
796 if (*addr->sas_addr.prv)
797 seq_putc(seq, '+');
798 } else if (!*addr->sas_addr.prv) {
799 seq_printf(seq, "%s", "(none)");
800 return;
801 }
802 if (*addr->sas_addr.prv) {
803 unsigned char *prv = addr->sas_addr.prv;
804 int *fields;
805 int i, j;
806
807 fields = *prv == ATM_AFI_E164 ? e164 : code;
808 for (i = 0; fields[i]; i++) {
809 for (j = fields[i]; j; j--)
810 seq_printf(seq, "%02X", *prv++);
811 if (fields[i+1])
812 seq_putc(seq, '.');
813 }
814 }
815}
816
817/* This means the neighbour entry has no attached VCC objects. */
818#define SEQ_NO_VCC_TOKEN ((void *) 2)
819
820static void atmarp_info(struct seq_file *seq, struct net_device *dev,
821 struct atmarp_entry *entry, struct clip_vcc *clip_vcc)
822{
823 unsigned long exp;
824 char buf[17];
825 int svc, llc, off;
826
827 svc = ((clip_vcc == SEQ_NO_VCC_TOKEN) ||
828 (sk_atm(clip_vcc->vcc)->sk_family == AF_ATMSVC));
829
830 llc = ((clip_vcc == SEQ_NO_VCC_TOKEN) ||
831 clip_vcc->encap);
832
833 if (clip_vcc == SEQ_NO_VCC_TOKEN)
834 exp = entry->neigh->used;
835 else
836 exp = clip_vcc->last_use;
837
838 exp = (jiffies - exp) / HZ;
839
840 seq_printf(seq, "%-6s%-4s%-4s%5ld ",
841 dev->name,
842 svc ? "SVC" : "PVC",
843 llc ? "LLC" : "NULL",
844 exp);
845
846 off = scnprintf(buf, sizeof(buf) - 1, "%d.%d.%d.%d",
847 NIPQUAD(entry->ip));
848 while (off < 16)
849 buf[off++] = ' ';
850 buf[off] = '\0';
851 seq_printf(seq, "%s", buf);
852
853 if (clip_vcc == SEQ_NO_VCC_TOKEN) {
854 if (time_before(jiffies, entry->expires))
855 seq_printf(seq, "(resolving)\n");
856 else
857 seq_printf(seq, "(expired, ref %d)\n",
858 atomic_read(&entry->neigh->refcnt));
859 } else if (!svc) {
860 seq_printf(seq, "%d.%d.%d\n",
861 clip_vcc->vcc->dev->number,
862 clip_vcc->vcc->vpi,
863 clip_vcc->vcc->vci);
864 } else {
865 svc_addr(seq, &clip_vcc->vcc->remote);
866 seq_putc(seq, '\n');
867 }
868}
869
870struct clip_seq_state {
871 /* This member must be first. */
872 struct neigh_seq_state ns;
873
874 /* Local to clip specific iteration. */
875 struct clip_vcc *vcc;
876};
877
878static struct clip_vcc *clip_seq_next_vcc(struct atmarp_entry *e,
879 struct clip_vcc *curr)
880{
881 if (!curr) {
882 curr = e->vccs;
883 if (!curr)
884 return SEQ_NO_VCC_TOKEN;
885 return curr;
886 }
887 if (curr == SEQ_NO_VCC_TOKEN)
888 return NULL;
889
890 curr = curr->next;
891
892 return curr;
893}
894
895static void *clip_seq_vcc_walk(struct clip_seq_state *state,
896 struct atmarp_entry *e, loff_t *pos)
897{
898 struct clip_vcc *vcc = state->vcc;
899
900 vcc = clip_seq_next_vcc(e, vcc);
901 if (vcc && pos != NULL) {
902 while (*pos) {
903 vcc = clip_seq_next_vcc(e, vcc);
904 if (!vcc)
905 break;
906 --(*pos);
907 }
908 }
909 state->vcc = vcc;
910
911 return vcc;
912}
913
914static void *clip_seq_sub_iter(struct neigh_seq_state *_state,
915 struct neighbour *n, loff_t *pos)
916{
917 struct clip_seq_state *state = (struct clip_seq_state *) _state;
918
919 return clip_seq_vcc_walk(state, NEIGH2ENTRY(n), pos);
920}
921
922static void *clip_seq_start(struct seq_file *seq, loff_t *pos)
923{
924 return neigh_seq_start(seq, pos, &clip_tbl, NEIGH_SEQ_NEIGH_ONLY);
925}
926
927static int clip_seq_show(struct seq_file *seq, void *v)
928{
929 static char atm_arp_banner[] =
930 "IPitf TypeEncp Idle IP address ATM address\n";
931
932 if (v == SEQ_START_TOKEN) {
933 seq_puts(seq, atm_arp_banner);
934 } else {
935 struct clip_seq_state *state = seq->private;
936 struct neighbour *n = v;
937 struct clip_vcc *vcc = state->vcc;
938
939 atmarp_info(seq, n->dev, NEIGH2ENTRY(n), vcc);
940 }
941 return 0;
942}
943
944static struct seq_operations arp_seq_ops = {
945 .start = clip_seq_start,
946 .next = neigh_seq_next,
947 .stop = neigh_seq_stop,
948 .show = clip_seq_show,
949};
950
951static int arp_seq_open(struct inode *inode, struct file *file)
952{
953 struct clip_seq_state *state;
954 struct seq_file *seq;
955 int rc = -EAGAIN;
956
957 state = kmalloc(sizeof(*state), GFP_KERNEL);
958 if (!state) {
959 rc = -ENOMEM;
960 goto out_kfree;
961 }
962 memset(state, 0, sizeof(*state));
963 state->ns.neigh_sub_iter = clip_seq_sub_iter;
964
965 rc = seq_open(file, &arp_seq_ops);
966 if (rc)
967 goto out_kfree;
968
969 seq = file->private_data;
970 seq->private = state;
971out:
972 return rc;
973
974out_kfree:
975 kfree(state);
976 goto out;
977}
978
979static struct file_operations arp_seq_fops = {
980 .open = arp_seq_open,
981 .read = seq_read,
982 .llseek = seq_lseek,
983 .release = seq_release_private,
984 .owner = THIS_MODULE
985};
986#endif
987
988static int __init atm_clip_init(void)
989{
990 neigh_table_init(&clip_tbl);
991
992 clip_tbl_hook = &clip_tbl;
993 register_atm_ioctl(&clip_ioctl_ops);
994
995#ifdef CONFIG_PROC_FS
996{
997 struct proc_dir_entry *p;
998
999 p = create_proc_entry("arp", S_IRUGO, atm_proc_root);
1000 if (p)
1001 p->proc_fops = &arp_seq_fops;
1002}
1003#endif
1004
1005 return 0;
1006}
1007
1008static void __exit atm_clip_exit(void)
1009{
1010 struct net_device *dev, *next;
1011
1012 remove_proc_entry("arp", atm_proc_root);
1013
1014 deregister_atm_ioctl(&clip_ioctl_ops);
1015
1016 /* First, stop the idle timer, so it stops banging
1017 * on the table.
1018 */
1019 if (start_timer == 0)
1020 del_timer(&idle_timer);
1021
1022 /* Next, purge the table, so that the device
1023 * unregister loop below does not hang due to
1024 * device references remaining in the table.
1025 */
1026 neigh_ifdown(&clip_tbl, NULL);
1027
1028 dev = clip_devs;
1029 while (dev) {
1030 next = PRIV(dev)->next;
1031 unregister_netdev(dev);
1032 free_netdev(dev);
1033 dev = next;
1034 }
1035
1036 /* Now it is safe to fully shutdown whole table. */
1037 neigh_table_clear(&clip_tbl);
1038
1039 clip_tbl_hook = NULL;
1040}
1041
1042module_init(atm_clip_init);
1043module_exit(atm_clip_exit);
1044
1045MODULE_LICENSE("GPL");
diff --git a/net/atm/common.c b/net/atm/common.c
new file mode 100644
index 000000000000..6d16be334ea0
--- /dev/null
+++ b/net/atm/common.c
@@ -0,0 +1,804 @@
1/* net/atm/common.c - ATM sockets (common part for PVC and SVC) */
2
3/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
4
5
6#include <linux/config.h>
7#include <linux/module.h>
8#include <linux/kmod.h>
9#include <linux/net.h> /* struct socket, struct proto_ops */
10#include <linux/atm.h> /* ATM stuff */
11#include <linux/atmdev.h>
12#include <linux/socket.h> /* SOL_SOCKET */
13#include <linux/errno.h> /* error codes */
14#include <linux/capability.h>
15#include <linux/mm.h> /* verify_area */
16#include <linux/sched.h>
17#include <linux/time.h> /* struct timeval */
18#include <linux/skbuff.h>
19#include <linux/bitops.h>
20#include <linux/init.h>
21#include <net/sock.h> /* struct sock */
22
23#include <asm/uaccess.h>
24#include <asm/atomic.h>
25#include <asm/poll.h>
26
27
28#include "resources.h" /* atm_find_dev */
29#include "common.h" /* prototypes */
30#include "protocols.h" /* atm_init_<transport> */
31#include "addr.h" /* address registry */
32#include "signaling.h" /* for WAITING and sigd_attach */
33
34
35#if 0
36#define DPRINTK(format,args...) printk(KERN_DEBUG format,##args)
37#else
38#define DPRINTK(format,args...)
39#endif
40
41struct hlist_head vcc_hash[VCC_HTABLE_SIZE];
42DEFINE_RWLOCK(vcc_sklist_lock);
43
44static void __vcc_insert_socket(struct sock *sk)
45{
46 struct atm_vcc *vcc = atm_sk(sk);
47 struct hlist_head *head = &vcc_hash[vcc->vci &
48 (VCC_HTABLE_SIZE - 1)];
49 sk->sk_hashent = vcc->vci & (VCC_HTABLE_SIZE - 1);
50 sk_add_node(sk, head);
51}
52
53void vcc_insert_socket(struct sock *sk)
54{
55 write_lock_irq(&vcc_sklist_lock);
56 __vcc_insert_socket(sk);
57 write_unlock_irq(&vcc_sklist_lock);
58}
59
60static void vcc_remove_socket(struct sock *sk)
61{
62 write_lock_irq(&vcc_sklist_lock);
63 sk_del_node_init(sk);
64 write_unlock_irq(&vcc_sklist_lock);
65}
66
67
68static struct sk_buff *alloc_tx(struct atm_vcc *vcc,unsigned int size)
69{
70 struct sk_buff *skb;
71 struct sock *sk = sk_atm(vcc);
72
73 if (atomic_read(&sk->sk_wmem_alloc) && !atm_may_send(vcc, size)) {
74 DPRINTK("Sorry: wmem_alloc = %d, size = %d, sndbuf = %d\n",
75 atomic_read(&sk->sk_wmem_alloc), size,
76 sk->sk_sndbuf);
77 return NULL;
78 }
79 while (!(skb = alloc_skb(size,GFP_KERNEL))) schedule();
80 DPRINTK("AlTx %d += %d\n", atomic_read(&sk->sk_wmem_alloc),
81 skb->truesize);
82 atomic_add(skb->truesize, &sk->sk_wmem_alloc);
83 return skb;
84}
85
86
87EXPORT_SYMBOL(vcc_hash);
88EXPORT_SYMBOL(vcc_sklist_lock);
89EXPORT_SYMBOL(vcc_insert_socket);
90
91static void vcc_sock_destruct(struct sock *sk)
92{
93 if (atomic_read(&sk->sk_rmem_alloc))
94 printk(KERN_DEBUG "vcc_sock_destruct: rmem leakage (%d bytes) detected.\n", atomic_read(&sk->sk_rmem_alloc));
95
96 if (atomic_read(&sk->sk_wmem_alloc))
97 printk(KERN_DEBUG "vcc_sock_destruct: wmem leakage (%d bytes) detected.\n", atomic_read(&sk->sk_wmem_alloc));
98}
99
100static void vcc_def_wakeup(struct sock *sk)
101{
102 read_lock(&sk->sk_callback_lock);
103 if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
104 wake_up(sk->sk_sleep);
105 read_unlock(&sk->sk_callback_lock);
106}
107
108static inline int vcc_writable(struct sock *sk)
109{
110 struct atm_vcc *vcc = atm_sk(sk);
111
112 return (vcc->qos.txtp.max_sdu +
113 atomic_read(&sk->sk_wmem_alloc)) <= sk->sk_sndbuf;
114}
115
116static void vcc_write_space(struct sock *sk)
117{
118 read_lock(&sk->sk_callback_lock);
119
120 if (vcc_writable(sk)) {
121 if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
122 wake_up_interruptible(sk->sk_sleep);
123
124 sk_wake_async(sk, 2, POLL_OUT);
125 }
126
127 read_unlock(&sk->sk_callback_lock);
128}
129
130static struct proto vcc_proto = {
131 .name = "VCC",
132 .owner = THIS_MODULE,
133 .obj_size = sizeof(struct atm_vcc),
134};
135
136int vcc_create(struct socket *sock, int protocol, int family)
137{
138 struct sock *sk;
139 struct atm_vcc *vcc;
140
141 sock->sk = NULL;
142 if (sock->type == SOCK_STREAM)
143 return -EINVAL;
144 sk = sk_alloc(family, GFP_KERNEL, &vcc_proto, 1);
145 if (!sk)
146 return -ENOMEM;
147 sock_init_data(sock, sk);
148 sk->sk_state_change = vcc_def_wakeup;
149 sk->sk_write_space = vcc_write_space;
150
151 vcc = atm_sk(sk);
152 vcc->dev = NULL;
153 memset(&vcc->local,0,sizeof(struct sockaddr_atmsvc));
154 memset(&vcc->remote,0,sizeof(struct sockaddr_atmsvc));
155 vcc->qos.txtp.max_sdu = 1 << 16; /* for meta VCs */
156 atomic_set(&sk->sk_wmem_alloc, 0);
157 atomic_set(&sk->sk_rmem_alloc, 0);
158 vcc->push = NULL;
159 vcc->pop = NULL;
160 vcc->push_oam = NULL;
161 vcc->vpi = vcc->vci = 0; /* no VCI/VPI yet */
162 vcc->atm_options = vcc->aal_options = 0;
163 sk->sk_destruct = vcc_sock_destruct;
164 return 0;
165}
166
167
168static void vcc_destroy_socket(struct sock *sk)
169{
170 struct atm_vcc *vcc = atm_sk(sk);
171 struct sk_buff *skb;
172
173 set_bit(ATM_VF_CLOSE, &vcc->flags);
174 clear_bit(ATM_VF_READY, &vcc->flags);
175 if (vcc->dev) {
176 if (vcc->dev->ops->close)
177 vcc->dev->ops->close(vcc);
178 if (vcc->push)
179 vcc->push(vcc, NULL); /* atmarpd has no push */
180
181 vcc_remove_socket(sk); /* no more receive */
182
183 while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
184 atm_return(vcc,skb->truesize);
185 kfree_skb(skb);
186 }
187
188 module_put(vcc->dev->ops->owner);
189 atm_dev_put(vcc->dev);
190 }
191}
192
193
194int vcc_release(struct socket *sock)
195{
196 struct sock *sk = sock->sk;
197
198 if (sk) {
199 lock_sock(sk);
200 vcc_destroy_socket(sock->sk);
201 release_sock(sk);
202 sock_put(sk);
203 }
204
205 return 0;
206}
207
208
209void vcc_release_async(struct atm_vcc *vcc, int reply)
210{
211 struct sock *sk = sk_atm(vcc);
212
213 set_bit(ATM_VF_CLOSE, &vcc->flags);
214 sk->sk_shutdown |= RCV_SHUTDOWN;
215 sk->sk_err = -reply;
216 clear_bit(ATM_VF_WAITING, &vcc->flags);
217 sk->sk_state_change(sk);
218}
219
220
221EXPORT_SYMBOL(vcc_release_async);
222
223
224static int adjust_tp(struct atm_trafprm *tp,unsigned char aal)
225{
226 int max_sdu;
227
228 if (!tp->traffic_class) return 0;
229 switch (aal) {
230 case ATM_AAL0:
231 max_sdu = ATM_CELL_SIZE-1;
232 break;
233 case ATM_AAL34:
234 max_sdu = ATM_MAX_AAL34_PDU;
235 break;
236 default:
237 printk(KERN_WARNING "ATM: AAL problems ... "
238 "(%d)\n",aal);
239 /* fall through */
240 case ATM_AAL5:
241 max_sdu = ATM_MAX_AAL5_PDU;
242 }
243 if (!tp->max_sdu) tp->max_sdu = max_sdu;
244 else if (tp->max_sdu > max_sdu) return -EINVAL;
245 if (!tp->max_cdv) tp->max_cdv = ATM_MAX_CDV;
246 return 0;
247}
248
249
250static int check_ci(struct atm_vcc *vcc, short vpi, int vci)
251{
252 struct hlist_head *head = &vcc_hash[vci &
253 (VCC_HTABLE_SIZE - 1)];
254 struct hlist_node *node;
255 struct sock *s;
256 struct atm_vcc *walk;
257
258 sk_for_each(s, node, head) {
259 walk = atm_sk(s);
260 if (walk->dev != vcc->dev)
261 continue;
262 if (test_bit(ATM_VF_ADDR, &walk->flags) && walk->vpi == vpi &&
263 walk->vci == vci && ((walk->qos.txtp.traffic_class !=
264 ATM_NONE && vcc->qos.txtp.traffic_class != ATM_NONE) ||
265 (walk->qos.rxtp.traffic_class != ATM_NONE &&
266 vcc->qos.rxtp.traffic_class != ATM_NONE)))
267 return -EADDRINUSE;
268 }
269
270 /* allow VCCs with same VPI/VCI iff they don't collide on
271 TX/RX (but we may refuse such sharing for other reasons,
272 e.g. if protocol requires to have both channels) */
273
274 return 0;
275}
276
277
278static int find_ci(struct atm_vcc *vcc, short *vpi, int *vci)
279{
280 static short p; /* poor man's per-device cache */
281 static int c;
282 short old_p;
283 int old_c;
284 int err;
285
286 if (*vpi != ATM_VPI_ANY && *vci != ATM_VCI_ANY) {
287 err = check_ci(vcc, *vpi, *vci);
288 return err;
289 }
290 /* last scan may have left values out of bounds for current device */
291 if (*vpi != ATM_VPI_ANY)
292 p = *vpi;
293 else if (p >= 1 << vcc->dev->ci_range.vpi_bits)
294 p = 0;
295 if (*vci != ATM_VCI_ANY)
296 c = *vci;
297 else if (c < ATM_NOT_RSV_VCI || c >= 1 << vcc->dev->ci_range.vci_bits)
298 c = ATM_NOT_RSV_VCI;
299 old_p = p;
300 old_c = c;
301 do {
302 if (!check_ci(vcc, p, c)) {
303 *vpi = p;
304 *vci = c;
305 return 0;
306 }
307 if (*vci == ATM_VCI_ANY) {
308 c++;
309 if (c >= 1 << vcc->dev->ci_range.vci_bits)
310 c = ATM_NOT_RSV_VCI;
311 }
312 if ((c == ATM_NOT_RSV_VCI || *vci != ATM_VCI_ANY) &&
313 *vpi == ATM_VPI_ANY) {
314 p++;
315 if (p >= 1 << vcc->dev->ci_range.vpi_bits) p = 0;
316 }
317 }
318 while (old_p != p || old_c != c);
319 return -EADDRINUSE;
320}
321
322
323static int __vcc_connect(struct atm_vcc *vcc, struct atm_dev *dev, short vpi,
324 int vci)
325{
326 struct sock *sk = sk_atm(vcc);
327 int error;
328
329 if ((vpi != ATM_VPI_UNSPEC && vpi != ATM_VPI_ANY &&
330 vpi >> dev->ci_range.vpi_bits) || (vci != ATM_VCI_UNSPEC &&
331 vci != ATM_VCI_ANY && vci >> dev->ci_range.vci_bits))
332 return -EINVAL;
333 if (vci > 0 && vci < ATM_NOT_RSV_VCI && !capable(CAP_NET_BIND_SERVICE))
334 return -EPERM;
335 error = 0;
336 if (!try_module_get(dev->ops->owner))
337 return -ENODEV;
338 vcc->dev = dev;
339 write_lock_irq(&vcc_sklist_lock);
340 if ((error = find_ci(vcc, &vpi, &vci))) {
341 write_unlock_irq(&vcc_sklist_lock);
342 goto fail_module_put;
343 }
344 vcc->vpi = vpi;
345 vcc->vci = vci;
346 __vcc_insert_socket(sk);
347 write_unlock_irq(&vcc_sklist_lock);
348 switch (vcc->qos.aal) {
349 case ATM_AAL0:
350 error = atm_init_aal0(vcc);
351 vcc->stats = &dev->stats.aal0;
352 break;
353 case ATM_AAL34:
354 error = atm_init_aal34(vcc);
355 vcc->stats = &dev->stats.aal34;
356 break;
357 case ATM_NO_AAL:
358 /* ATM_AAL5 is also used in the "0 for default" case */
359 vcc->qos.aal = ATM_AAL5;
360 /* fall through */
361 case ATM_AAL5:
362 error = atm_init_aal5(vcc);
363 vcc->stats = &dev->stats.aal5;
364 break;
365 default:
366 error = -EPROTOTYPE;
367 }
368 if (!error) error = adjust_tp(&vcc->qos.txtp,vcc->qos.aal);
369 if (!error) error = adjust_tp(&vcc->qos.rxtp,vcc->qos.aal);
370 if (error)
371 goto fail;
372 DPRINTK("VCC %d.%d, AAL %d\n",vpi,vci,vcc->qos.aal);
373 DPRINTK(" TX: %d, PCR %d..%d, SDU %d\n",vcc->qos.txtp.traffic_class,
374 vcc->qos.txtp.min_pcr,vcc->qos.txtp.max_pcr,vcc->qos.txtp.max_sdu);
375 DPRINTK(" RX: %d, PCR %d..%d, SDU %d\n",vcc->qos.rxtp.traffic_class,
376 vcc->qos.rxtp.min_pcr,vcc->qos.rxtp.max_pcr,vcc->qos.rxtp.max_sdu);
377
378 if (dev->ops->open) {
379 if ((error = dev->ops->open(vcc)))
380 goto fail;
381 }
382 return 0;
383
384fail:
385 vcc_remove_socket(sk);
386fail_module_put:
387 module_put(dev->ops->owner);
388 /* ensure we get dev module ref count correct */
389 vcc->dev = NULL;
390 return error;
391}
392
393
394int vcc_connect(struct socket *sock, int itf, short vpi, int vci)
395{
396 struct atm_dev *dev;
397 struct atm_vcc *vcc = ATM_SD(sock);
398 int error;
399
400 DPRINTK("vcc_connect (vpi %d, vci %d)\n",vpi,vci);
401 if (sock->state == SS_CONNECTED)
402 return -EISCONN;
403 if (sock->state != SS_UNCONNECTED)
404 return -EINVAL;
405 if (!(vpi || vci))
406 return -EINVAL;
407
408 if (vpi != ATM_VPI_UNSPEC && vci != ATM_VCI_UNSPEC)
409 clear_bit(ATM_VF_PARTIAL,&vcc->flags);
410 else
411 if (test_bit(ATM_VF_PARTIAL,&vcc->flags))
412 return -EINVAL;
413 DPRINTK("vcc_connect (TX: cl %d,bw %d-%d,sdu %d; "
414 "RX: cl %d,bw %d-%d,sdu %d,AAL %s%d)\n",
415 vcc->qos.txtp.traffic_class,vcc->qos.txtp.min_pcr,
416 vcc->qos.txtp.max_pcr,vcc->qos.txtp.max_sdu,
417 vcc->qos.rxtp.traffic_class,vcc->qos.rxtp.min_pcr,
418 vcc->qos.rxtp.max_pcr,vcc->qos.rxtp.max_sdu,
419 vcc->qos.aal == ATM_AAL5 ? "" : vcc->qos.aal == ATM_AAL0 ? "" :
420 " ??? code ",vcc->qos.aal == ATM_AAL0 ? 0 : vcc->qos.aal);
421 if (!test_bit(ATM_VF_HASQOS, &vcc->flags))
422 return -EBADFD;
423 if (vcc->qos.txtp.traffic_class == ATM_ANYCLASS ||
424 vcc->qos.rxtp.traffic_class == ATM_ANYCLASS)
425 return -EINVAL;
426 if (itf != ATM_ITF_ANY) {
427 dev = atm_dev_lookup(itf);
428 if (!dev)
429 return -ENODEV;
430 error = __vcc_connect(vcc, dev, vpi, vci);
431 if (error) {
432 atm_dev_put(dev);
433 return error;
434 }
435 } else {
436 struct list_head *p, *next;
437
438 dev = NULL;
439 spin_lock(&atm_dev_lock);
440 list_for_each_safe(p, next, &atm_devs) {
441 dev = list_entry(p, struct atm_dev, dev_list);
442 atm_dev_hold(dev);
443 spin_unlock(&atm_dev_lock);
444 if (!__vcc_connect(vcc, dev, vpi, vci))
445 break;
446 atm_dev_put(dev);
447 dev = NULL;
448 spin_lock(&atm_dev_lock);
449 }
450 spin_unlock(&atm_dev_lock);
451 if (!dev)
452 return -ENODEV;
453 }
454 if (vpi == ATM_VPI_UNSPEC || vci == ATM_VCI_UNSPEC)
455 set_bit(ATM_VF_PARTIAL,&vcc->flags);
456 if (test_bit(ATM_VF_READY,&ATM_SD(sock)->flags))
457 sock->state = SS_CONNECTED;
458 return 0;
459}
460
461
462int vcc_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
463 size_t size, int flags)
464{
465 struct sock *sk = sock->sk;
466 struct atm_vcc *vcc;
467 struct sk_buff *skb;
468 int copied, error = -EINVAL;
469
470 if (sock->state != SS_CONNECTED)
471 return -ENOTCONN;
472 if (flags & ~MSG_DONTWAIT) /* only handle MSG_DONTWAIT */
473 return -EOPNOTSUPP;
474 vcc = ATM_SD(sock);
475 if (test_bit(ATM_VF_RELEASED,&vcc->flags) ||
476 test_bit(ATM_VF_CLOSE,&vcc->flags) ||
477 !test_bit(ATM_VF_READY, &vcc->flags))
478 return 0;
479
480 skb = skb_recv_datagram(sk, flags, flags & MSG_DONTWAIT, &error);
481 if (!skb)
482 return error;
483
484 copied = skb->len;
485 if (copied > size) {
486 copied = size;
487 msg->msg_flags |= MSG_TRUNC;
488 }
489
490 error = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
491 if (error)
492 return error;
493 sock_recv_timestamp(msg, sk, skb);
494 DPRINTK("RcvM %d -= %d\n", atomic_read(&sk->rmem_alloc), skb->truesize);
495 atm_return(vcc, skb->truesize);
496 skb_free_datagram(sk, skb);
497 return copied;
498}
499
500
501int vcc_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m,
502 size_t total_len)
503{
504 struct sock *sk = sock->sk;
505 DEFINE_WAIT(wait);
506 struct atm_vcc *vcc;
507 struct sk_buff *skb;
508 int eff,error;
509 const void __user *buff;
510 int size;
511
512 lock_sock(sk);
513 if (sock->state != SS_CONNECTED) {
514 error = -ENOTCONN;
515 goto out;
516 }
517 if (m->msg_name) {
518 error = -EISCONN;
519 goto out;
520 }
521 if (m->msg_iovlen != 1) {
522 error = -ENOSYS; /* fix this later @@@ */
523 goto out;
524 }
525 buff = m->msg_iov->iov_base;
526 size = m->msg_iov->iov_len;
527 vcc = ATM_SD(sock);
528 if (test_bit(ATM_VF_RELEASED, &vcc->flags) ||
529 test_bit(ATM_VF_CLOSE, &vcc->flags) ||
530 !test_bit(ATM_VF_READY, &vcc->flags)) {
531 error = -EPIPE;
532 send_sig(SIGPIPE, current, 0);
533 goto out;
534 }
535 if (!size) {
536 error = 0;
537 goto out;
538 }
539 if (size < 0 || size > vcc->qos.txtp.max_sdu) {
540 error = -EMSGSIZE;
541 goto out;
542 }
543 /* verify_area is done by net/socket.c */
544 eff = (size+3) & ~3; /* align to word boundary */
545 prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
546 error = 0;
547 while (!(skb = alloc_tx(vcc,eff))) {
548 if (m->msg_flags & MSG_DONTWAIT) {
549 error = -EAGAIN;
550 break;
551 }
552 schedule();
553 if (signal_pending(current)) {
554 error = -ERESTARTSYS;
555 break;
556 }
557 if (test_bit(ATM_VF_RELEASED,&vcc->flags) ||
558 test_bit(ATM_VF_CLOSE,&vcc->flags) ||
559 !test_bit(ATM_VF_READY,&vcc->flags)) {
560 error = -EPIPE;
561 send_sig(SIGPIPE, current, 0);
562 break;
563 }
564 prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
565 }
566 finish_wait(sk->sk_sleep, &wait);
567 if (error)
568 goto out;
569 skb->dev = NULL; /* for paths shared with net_device interfaces */
570 ATM_SKB(skb)->atm_options = vcc->atm_options;
571 if (copy_from_user(skb_put(skb,size),buff,size)) {
572 kfree_skb(skb);
573 error = -EFAULT;
574 goto out;
575 }
576 if (eff != size) memset(skb->data+size,0,eff-size);
577 error = vcc->dev->ops->send(vcc,skb);
578 error = error ? error : size;
579out:
580 release_sock(sk);
581 return error;
582}
583
584
585unsigned int vcc_poll(struct file *file, struct socket *sock, poll_table *wait)
586{
587 struct sock *sk = sock->sk;
588 struct atm_vcc *vcc;
589 unsigned int mask;
590
591 poll_wait(file, sk->sk_sleep, wait);
592 mask = 0;
593
594 vcc = ATM_SD(sock);
595
596 /* exceptional events */
597 if (sk->sk_err)
598 mask = POLLERR;
599
600 if (test_bit(ATM_VF_RELEASED, &vcc->flags) ||
601 test_bit(ATM_VF_CLOSE, &vcc->flags))
602 mask |= POLLHUP;
603
604 /* readable? */
605 if (!skb_queue_empty(&sk->sk_receive_queue))
606 mask |= POLLIN | POLLRDNORM;
607
608 /* writable? */
609 if (sock->state == SS_CONNECTING &&
610 test_bit(ATM_VF_WAITING, &vcc->flags))
611 return mask;
612
613 if (vcc->qos.txtp.traffic_class != ATM_NONE &&
614 vcc_writable(sk))
615 mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
616
617 return mask;
618}
619
620
621static int atm_change_qos(struct atm_vcc *vcc,struct atm_qos *qos)
622{
623 int error;
624
625 /*
626 * Don't let the QoS change the already connected AAL type nor the
627 * traffic class.
628 */
629 if (qos->aal != vcc->qos.aal ||
630 qos->rxtp.traffic_class != vcc->qos.rxtp.traffic_class ||
631 qos->txtp.traffic_class != vcc->qos.txtp.traffic_class)
632 return -EINVAL;
633 error = adjust_tp(&qos->txtp,qos->aal);
634 if (!error) error = adjust_tp(&qos->rxtp,qos->aal);
635 if (error) return error;
636 if (!vcc->dev->ops->change_qos) return -EOPNOTSUPP;
637 if (sk_atm(vcc)->sk_family == AF_ATMPVC)
638 return vcc->dev->ops->change_qos(vcc,qos,ATM_MF_SET);
639 return svc_change_qos(vcc,qos);
640}
641
642
643static int check_tp(struct atm_trafprm *tp)
644{
645 /* @@@ Should be merged with adjust_tp */
646 if (!tp->traffic_class || tp->traffic_class == ATM_ANYCLASS) return 0;
647 if (tp->traffic_class != ATM_UBR && !tp->min_pcr && !tp->pcr &&
648 !tp->max_pcr) return -EINVAL;
649 if (tp->min_pcr == ATM_MAX_PCR) return -EINVAL;
650 if (tp->min_pcr && tp->max_pcr && tp->max_pcr != ATM_MAX_PCR &&
651 tp->min_pcr > tp->max_pcr) return -EINVAL;
652 /*
653 * We allow pcr to be outside [min_pcr,max_pcr], because later
654 * adjustment may still push it in the valid range.
655 */
656 return 0;
657}
658
659
660static int check_qos(struct atm_qos *qos)
661{
662 int error;
663
664 if (!qos->txtp.traffic_class && !qos->rxtp.traffic_class)
665 return -EINVAL;
666 if (qos->txtp.traffic_class != qos->rxtp.traffic_class &&
667 qos->txtp.traffic_class && qos->rxtp.traffic_class &&
668 qos->txtp.traffic_class != ATM_ANYCLASS &&
669 qos->rxtp.traffic_class != ATM_ANYCLASS) return -EINVAL;
670 error = check_tp(&qos->txtp);
671 if (error) return error;
672 return check_tp(&qos->rxtp);
673}
674
675int vcc_setsockopt(struct socket *sock, int level, int optname,
676 char __user *optval, int optlen)
677{
678 struct atm_vcc *vcc;
679 unsigned long value;
680 int error;
681
682 if (__SO_LEVEL_MATCH(optname, level) && optlen != __SO_SIZE(optname))
683 return -EINVAL;
684
685 vcc = ATM_SD(sock);
686 switch (optname) {
687 case SO_ATMQOS:
688 {
689 struct atm_qos qos;
690
691 if (copy_from_user(&qos,optval,sizeof(qos)))
692 return -EFAULT;
693 error = check_qos(&qos);
694 if (error) return error;
695 if (sock->state == SS_CONNECTED)
696 return atm_change_qos(vcc,&qos);
697 if (sock->state != SS_UNCONNECTED)
698 return -EBADFD;
699 vcc->qos = qos;
700 set_bit(ATM_VF_HASQOS,&vcc->flags);
701 return 0;
702 }
703 case SO_SETCLP:
704 if (get_user(value,(unsigned long __user *)optval))
705 return -EFAULT;
706 if (value) vcc->atm_options |= ATM_ATMOPT_CLP;
707 else vcc->atm_options &= ~ATM_ATMOPT_CLP;
708 return 0;
709 default:
710 if (level == SOL_SOCKET) return -EINVAL;
711 break;
712 }
713 if (!vcc->dev || !vcc->dev->ops->setsockopt) return -EINVAL;
714 return vcc->dev->ops->setsockopt(vcc,level,optname,optval,optlen);
715}
716
717
718int vcc_getsockopt(struct socket *sock, int level, int optname,
719 char __user *optval, int __user *optlen)
720{
721 struct atm_vcc *vcc;
722 int len;
723
724 if (get_user(len, optlen))
725 return -EFAULT;
726 if (__SO_LEVEL_MATCH(optname, level) && len != __SO_SIZE(optname))
727 return -EINVAL;
728
729 vcc = ATM_SD(sock);
730 switch (optname) {
731 case SO_ATMQOS:
732 if (!test_bit(ATM_VF_HASQOS,&vcc->flags))
733 return -EINVAL;
734 return copy_to_user(optval,&vcc->qos,sizeof(vcc->qos)) ?
735 -EFAULT : 0;
736 case SO_SETCLP:
737 return put_user(vcc->atm_options & ATM_ATMOPT_CLP ? 1 :
738 0,(unsigned long __user *)optval) ? -EFAULT : 0;
739 case SO_ATMPVC:
740 {
741 struct sockaddr_atmpvc pvc;
742
743 if (!vcc->dev ||
744 !test_bit(ATM_VF_ADDR,&vcc->flags))
745 return -ENOTCONN;
746 pvc.sap_family = AF_ATMPVC;
747 pvc.sap_addr.itf = vcc->dev->number;
748 pvc.sap_addr.vpi = vcc->vpi;
749 pvc.sap_addr.vci = vcc->vci;
750 return copy_to_user(optval,&pvc,sizeof(pvc)) ?
751 -EFAULT : 0;
752 }
753 default:
754 if (level == SOL_SOCKET) return -EINVAL;
755 break;
756 }
757 if (!vcc->dev || !vcc->dev->ops->getsockopt) return -EINVAL;
758 return vcc->dev->ops->getsockopt(vcc, level, optname, optval, len);
759}
760
761static int __init atm_init(void)
762{
763 int error;
764
765 if ((error = proto_register(&vcc_proto, 0)) < 0)
766 goto out;
767
768 if ((error = atmpvc_init()) < 0) {
769 printk(KERN_ERR "atmpvc_init() failed with %d\n", error);
770 goto out_unregister_vcc_proto;
771 }
772 if ((error = atmsvc_init()) < 0) {
773 printk(KERN_ERR "atmsvc_init() failed with %d\n", error);
774 goto out_atmpvc_exit;
775 }
776 if ((error = atm_proc_init()) < 0) {
777 printk(KERN_ERR "atm_proc_init() failed with %d\n",error);
778 goto out_atmsvc_exit;
779 }
780out:
781 return error;
782out_atmsvc_exit:
783 atmsvc_exit();
784out_atmpvc_exit:
785 atmsvc_exit();
786out_unregister_vcc_proto:
787 proto_unregister(&vcc_proto);
788 goto out;
789}
790
791static void __exit atm_exit(void)
792{
793 atm_proc_exit();
794 atmsvc_exit();
795 atmpvc_exit();
796 proto_unregister(&vcc_proto);
797}
798
799module_init(atm_init);
800module_exit(atm_exit);
801
802MODULE_LICENSE("GPL");
803MODULE_ALIAS_NETPROTO(PF_ATMPVC);
804MODULE_ALIAS_NETPROTO(PF_ATMSVC);
diff --git a/net/atm/common.h b/net/atm/common.h
new file mode 100644
index 000000000000..e49ed41c0e33
--- /dev/null
+++ b/net/atm/common.h
@@ -0,0 +1,50 @@
1/* net/atm/common.h - ATM sockets (common part for PVC and SVC) */
2
3/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
4
5
6#ifndef NET_ATM_COMMON_H
7#define NET_ATM_COMMON_H
8
9#include <linux/net.h>
10#include <linux/poll.h> /* for poll_table */
11
12
13int vcc_create(struct socket *sock, int protocol, int family);
14int vcc_release(struct socket *sock);
15int vcc_connect(struct socket *sock, int itf, short vpi, int vci);
16int vcc_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
17 size_t size, int flags);
18int vcc_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m,
19 size_t total_len);
20unsigned int vcc_poll(struct file *file, struct socket *sock, poll_table *wait);
21int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
22int vcc_setsockopt(struct socket *sock, int level, int optname,
23 char __user *optval, int optlen);
24int vcc_getsockopt(struct socket *sock, int level, int optname,
25 char __user *optval, int __user *optlen);
26
27int atmpvc_init(void);
28void atmpvc_exit(void);
29int atmsvc_init(void);
30void atmsvc_exit(void);
31
32#ifdef CONFIG_PROC_FS
33int atm_proc_init(void);
34void atm_proc_exit(void);
35#else
36static inline int atm_proc_init(void)
37{
38 return 0;
39}
40
41static inline void atm_proc_exit(void)
42{
43 /* nothing */
44}
45#endif /* CONFIG_PROC_FS */
46
47/* SVC */
48int svc_change_qos(struct atm_vcc *vcc,struct atm_qos *qos);
49
50#endif
diff --git a/net/atm/ioctl.c b/net/atm/ioctl.c
new file mode 100644
index 000000000000..4dbb5af34a5e
--- /dev/null
+++ b/net/atm/ioctl.c
@@ -0,0 +1,139 @@
1/* ATM ioctl handling */
2
3/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
4/* 2003 John Levon <levon@movementarian.org> */
5
6
7#include <linux/config.h>
8#include <linux/module.h>
9#include <linux/kmod.h>
10#include <linux/net.h> /* struct socket, struct proto_ops */
11#include <linux/atm.h> /* ATM stuff */
12#include <linux/atmdev.h>
13#include <linux/atmclip.h> /* CLIP_*ENCAP */
14#include <linux/atmarp.h> /* manifest constants */
15#include <linux/sonet.h> /* for ioctls */
16#include <linux/atmsvc.h>
17#include <linux/atmmpc.h>
18#include <net/atmclip.h>
19#include <linux/atmlec.h>
20#include <asm/ioctls.h>
21
22#include "resources.h"
23#include "signaling.h" /* for WAITING and sigd_attach */
24
25
26static DECLARE_MUTEX(ioctl_mutex);
27static LIST_HEAD(ioctl_list);
28
29
30void register_atm_ioctl(struct atm_ioctl *ioctl)
31{
32 down(&ioctl_mutex);
33 list_add_tail(&ioctl->list, &ioctl_list);
34 up(&ioctl_mutex);
35}
36
37void deregister_atm_ioctl(struct atm_ioctl *ioctl)
38{
39 down(&ioctl_mutex);
40 list_del(&ioctl->list);
41 up(&ioctl_mutex);
42}
43
44EXPORT_SYMBOL(register_atm_ioctl);
45EXPORT_SYMBOL(deregister_atm_ioctl);
46
47int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
48{
49 struct sock *sk = sock->sk;
50 struct atm_vcc *vcc;
51 int error;
52 struct list_head * pos;
53 void __user *argp = (void __user *)arg;
54
55 vcc = ATM_SD(sock);
56 switch (cmd) {
57 case SIOCOUTQ:
58 if (sock->state != SS_CONNECTED ||
59 !test_bit(ATM_VF_READY, &vcc->flags)) {
60 error = -EINVAL;
61 goto done;
62 }
63 error = put_user(sk->sk_sndbuf -
64 atomic_read(&sk->sk_wmem_alloc),
65 (int __user *) argp) ? -EFAULT : 0;
66 goto done;
67 case SIOCINQ:
68 {
69 struct sk_buff *skb;
70
71 if (sock->state != SS_CONNECTED) {
72 error = -EINVAL;
73 goto done;
74 }
75 skb = skb_peek(&sk->sk_receive_queue);
76 error = put_user(skb ? skb->len : 0,
77 (int __user *)argp) ? -EFAULT : 0;
78 goto done;
79 }
80 case SIOCGSTAMP: /* borrowed from IP */
81 error = sock_get_timestamp(sk, argp);
82 goto done;
83 case ATM_SETSC:
84 printk(KERN_WARNING "ATM_SETSC is obsolete\n");
85 error = 0;
86 goto done;
87 case ATMSIGD_CTRL:
88 if (!capable(CAP_NET_ADMIN)) {
89 error = -EPERM;
90 goto done;
91 }
92 /*
93 * The user/kernel protocol for exchanging signalling
94 * info uses kernel pointers as opaque references,
95 * so the holder of the file descriptor can scribble
96 * on the kernel... so we should make sure that we
97 * have the same privledges that /proc/kcore needs
98 */
99 if (!capable(CAP_SYS_RAWIO)) {
100 error = -EPERM;
101 goto done;
102 }
103 error = sigd_attach(vcc);
104 if (!error)
105 sock->state = SS_CONNECTED;
106 goto done;
107 default:
108 break;
109 }
110
111 if (cmd == ATMMPC_CTRL || cmd == ATMMPC_DATA)
112 request_module("mpoa");
113 if (cmd == ATMARPD_CTRL)
114 request_module("clip");
115 if (cmd == ATMLEC_CTRL)
116 request_module("lec");
117
118 error = -ENOIOCTLCMD;
119
120 down(&ioctl_mutex);
121 list_for_each(pos, &ioctl_list) {
122 struct atm_ioctl * ic = list_entry(pos, struct atm_ioctl, list);
123 if (try_module_get(ic->owner)) {
124 error = ic->ioctl(sock, cmd, arg);
125 module_put(ic->owner);
126 if (error != -ENOIOCTLCMD)
127 break;
128 }
129 }
130 up(&ioctl_mutex);
131
132 if (error != -ENOIOCTLCMD)
133 goto done;
134
135 error = atm_dev_ioctl(cmd, argp);
136
137done:
138 return error;
139}
diff --git a/net/atm/ipcommon.c b/net/atm/ipcommon.c
new file mode 100644
index 000000000000..181a3002d8ad
--- /dev/null
+++ b/net/atm/ipcommon.c
@@ -0,0 +1,61 @@
1/* net/atm/ipcommon.c - Common items for all ways of doing IP over ATM */
2
3/* Written 1996-2000 by Werner Almesberger, EPFL LRC/ICA */
4
5
6#include <linux/module.h>
7#include <linux/string.h>
8#include <linux/skbuff.h>
9#include <linux/netdevice.h>
10#include <linux/in.h>
11#include <linux/atmdev.h>
12#include <linux/atmclip.h>
13
14#include "common.h"
15#include "ipcommon.h"
16
17
18#if 0
19#define DPRINTK(format,args...) printk(KERN_DEBUG format,##args)
20#else
21#define DPRINTK(format,args...)
22#endif
23
24
25/*
26 * skb_migrate appends the list at "from" to "to", emptying "from" in the
27 * process. skb_migrate is atomic with respect to all other skb operations on
28 * "from" and "to". Note that it locks both lists at the same time, so beware
29 * of potential deadlocks.
30 *
31 * This function should live in skbuff.c or skbuff.h.
32 */
33
34
35void skb_migrate(struct sk_buff_head *from,struct sk_buff_head *to)
36{
37 struct sk_buff *skb;
38 unsigned long flags;
39 struct sk_buff *skb_from = (struct sk_buff *) from;
40 struct sk_buff *skb_to = (struct sk_buff *) to;
41 struct sk_buff *prev;
42
43 spin_lock_irqsave(&from->lock,flags);
44 spin_lock(&to->lock);
45 prev = from->prev;
46 from->next->prev = to->prev;
47 prev->next = skb_to;
48 to->prev->next = from->next;
49 to->prev = from->prev;
50 for (skb = from->next; skb != skb_to; skb = skb->next)
51 skb->list = to;
52 to->qlen += from->qlen;
53 spin_unlock(&to->lock);
54 from->prev = skb_from;
55 from->next = skb_from;
56 from->qlen = 0;
57 spin_unlock_irqrestore(&from->lock,flags);
58}
59
60
61EXPORT_SYMBOL(skb_migrate);
diff --git a/net/atm/ipcommon.h b/net/atm/ipcommon.h
new file mode 100644
index 000000000000..d72165f60939
--- /dev/null
+++ b/net/atm/ipcommon.h
@@ -0,0 +1,22 @@
1/* net/atm/ipcommon.h - Common items for all ways of doing IP over ATM */
2
3/* Written 1996-2000 by Werner Almesberger, EPFL LRC/ICA */
4
5
6#ifndef NET_ATM_IPCOMMON_H
7#define NET_ATM_IPCOMMON_H
8
9
10#include <linux/string.h>
11#include <linux/skbuff.h>
12#include <linux/netdevice.h>
13#include <linux/atmdev.h>
14
15/*
16 * Appends all skbs from "from" to "to". The operation is atomic with respect
17 * to all other skb operations on "from" or "to".
18 */
19
20void skb_migrate(struct sk_buff_head *from,struct sk_buff_head *to);
21
22#endif
diff --git a/net/atm/lec.c b/net/atm/lec.c
new file mode 100644
index 000000000000..a0752487026d
--- /dev/null
+++ b/net/atm/lec.c
@@ -0,0 +1,2538 @@
1/*
2 * lec.c: Lan Emulation driver
3 * Marko Kiiskila mkiiskila@yahoo.com
4 *
5 */
6
7#include <linux/config.h>
8#include <linux/kernel.h>
9#include <linux/bitops.h>
10
11/* We are ethernet device */
12#include <linux/if_ether.h>
13#include <linux/netdevice.h>
14#include <linux/etherdevice.h>
15#include <net/sock.h>
16#include <linux/skbuff.h>
17#include <linux/ip.h>
18#include <asm/byteorder.h>
19#include <asm/uaccess.h>
20#include <net/arp.h>
21#include <net/dst.h>
22#include <linux/proc_fs.h>
23#include <linux/spinlock.h>
24#include <linux/proc_fs.h>
25#include <linux/seq_file.h>
26
27/* TokenRing if needed */
28#ifdef CONFIG_TR
29#include <linux/trdevice.h>
30#endif
31
32/* And atm device */
33#include <linux/atmdev.h>
34#include <linux/atmlec.h>
35
36/* Proxy LEC knows about bridging */
37#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
38#include <linux/if_bridge.h>
39#include "../bridge/br_private.h"
40
41static unsigned char bridge_ula_lec[] = {0x01, 0x80, 0xc2, 0x00, 0x00};
42#endif
43
44/* Modular too */
45#include <linux/module.h>
46#include <linux/init.h>
47
48#include "lec.h"
49#include "lec_arpc.h"
50#include "resources.h"
51
52#if 0
53#define DPRINTK printk
54#else
55#define DPRINTK(format,args...)
56#endif
57
58#define DUMP_PACKETS 0 /* 0 = None,
59 * 1 = 30 first bytes
60 * 2 = Whole packet
61 */
62
63#define LEC_UNRES_QUE_LEN 8 /* number of tx packets to queue for a
64 single destination while waiting for SVC */
65
66static int lec_open(struct net_device *dev);
67static int lec_start_xmit(struct sk_buff *skb, struct net_device *dev);
68static int lec_close(struct net_device *dev);
69static struct net_device_stats *lec_get_stats(struct net_device *dev);
70static void lec_init(struct net_device *dev);
71static struct lec_arp_table* lec_arp_find(struct lec_priv *priv,
72 unsigned char *mac_addr);
73static int lec_arp_remove(struct lec_priv *priv,
74 struct lec_arp_table *to_remove);
75/* LANE2 functions */
76static void lane2_associate_ind (struct net_device *dev, u8 *mac_address,
77 u8 *tlvs, u32 sizeoftlvs);
78static int lane2_resolve(struct net_device *dev, u8 *dst_mac, int force,
79 u8 **tlvs, u32 *sizeoftlvs);
80static int lane2_associate_req (struct net_device *dev, u8 *lan_dst,
81 u8 *tlvs, u32 sizeoftlvs);
82
83static int lec_addr_delete(struct lec_priv *priv, unsigned char *atm_addr,
84 unsigned long permanent);
85static void lec_arp_check_empties(struct lec_priv *priv,
86 struct atm_vcc *vcc, struct sk_buff *skb);
87static void lec_arp_destroy(struct lec_priv *priv);
88static void lec_arp_init(struct lec_priv *priv);
89static struct atm_vcc* lec_arp_resolve(struct lec_priv *priv,
90 unsigned char *mac_to_find,
91 int is_rdesc,
92 struct lec_arp_table **ret_entry);
93static void lec_arp_update(struct lec_priv *priv, unsigned char *mac_addr,
94 unsigned char *atm_addr, unsigned long remoteflag,
95 unsigned int targetless_le_arp);
96static void lec_flush_complete(struct lec_priv *priv, unsigned long tran_id);
97static int lec_mcast_make(struct lec_priv *priv, struct atm_vcc *vcc);
98static void lec_set_flush_tran_id(struct lec_priv *priv,
99 unsigned char *atm_addr,
100 unsigned long tran_id);
101static void lec_vcc_added(struct lec_priv *priv, struct atmlec_ioc *ioc_data,
102 struct atm_vcc *vcc,
103 void (*old_push)(struct atm_vcc *vcc, struct sk_buff *skb));
104static void lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc);
105
106static struct lane2_ops lane2_ops = {
107 lane2_resolve, /* resolve, spec 3.1.3 */
108 lane2_associate_req, /* associate_req, spec 3.1.4 */
109 NULL /* associate indicator, spec 3.1.5 */
110};
111
112static unsigned char bus_mac[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff};
113
114/* Device structures */
115static struct net_device *dev_lec[MAX_LEC_ITF];
116
117#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
118static void lec_handle_bridge(struct sk_buff *skb, struct net_device *dev)
119{
120 struct ethhdr *eth;
121 char *buff;
122 struct lec_priv *priv;
123
124 /* Check if this is a BPDU. If so, ask zeppelin to send
125 * LE_TOPOLOGY_REQUEST with the same value of Topology Change bit
126 * as the Config BPDU has */
127 eth = (struct ethhdr *)skb->data;
128 buff = skb->data + skb->dev->hard_header_len;
129 if (*buff++ == 0x42 && *buff++ == 0x42 && *buff++ == 0x03) {
130 struct sock *sk;
131 struct sk_buff *skb2;
132 struct atmlec_msg *mesg;
133
134 skb2 = alloc_skb(sizeof(struct atmlec_msg), GFP_ATOMIC);
135 if (skb2 == NULL) return;
136 skb2->len = sizeof(struct atmlec_msg);
137 mesg = (struct atmlec_msg *)skb2->data;
138 mesg->type = l_topology_change;
139 buff += 4;
140 mesg->content.normal.flag = *buff & 0x01; /* 0x01 is topology change */
141
142 priv = (struct lec_priv *)dev->priv;
143 atm_force_charge(priv->lecd, skb2->truesize);
144 sk = sk_atm(priv->lecd);
145 skb_queue_tail(&sk->sk_receive_queue, skb2);
146 sk->sk_data_ready(sk, skb2->len);
147 }
148
149 return;
150}
151#endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */
152
153/*
154 * Modelled after tr_type_trans
155 * All multicast and ARE or STE frames go to BUS.
156 * Non source routed frames go by destination address.
157 * Last hop source routed frames go by destination address.
158 * Not last hop source routed frames go by _next_ route descriptor.
159 * Returns pointer to destination MAC address or fills in rdesc
160 * and returns NULL.
161 */
162#ifdef CONFIG_TR
163static unsigned char *get_tr_dst(unsigned char *packet, unsigned char *rdesc)
164{
165 struct trh_hdr *trh;
166 int riflen, num_rdsc;
167
168 trh = (struct trh_hdr *)packet;
169 if (trh->daddr[0] & (uint8_t)0x80)
170 return bus_mac; /* multicast */
171
172 if (trh->saddr[0] & TR_RII) {
173 riflen = (ntohs(trh->rcf) & TR_RCF_LEN_MASK) >> 8;
174 if ((ntohs(trh->rcf) >> 13) != 0)
175 return bus_mac; /* ARE or STE */
176 }
177 else
178 return trh->daddr; /* not source routed */
179
180 if (riflen < 6)
181 return trh->daddr; /* last hop, source routed */
182
183 /* riflen is 6 or more, packet has more than one route descriptor */
184 num_rdsc = (riflen/2) - 1;
185 memset(rdesc, 0, ETH_ALEN);
186 /* offset 4 comes from LAN destination field in LE control frames */
187 if (trh->rcf & htons((uint16_t)TR_RCF_DIR_BIT))
188 memcpy(&rdesc[4], &trh->rseg[num_rdsc-2], sizeof(uint16_t));
189 else {
190 memcpy(&rdesc[4], &trh->rseg[1], sizeof(uint16_t));
191 rdesc[5] = ((ntohs(trh->rseg[0]) & 0x000f) | (rdesc[5] & 0xf0));
192 }
193
194 return NULL;
195}
196#endif /* CONFIG_TR */
197
198/*
199 * Open/initialize the netdevice. This is called (in the current kernel)
200 * sometime after booting when the 'ifconfig' program is run.
201 *
202 * This routine should set everything up anew at each open, even
203 * registers that "should" only need to be set once at boot, so that
204 * there is non-reboot way to recover if something goes wrong.
205 */
206
207static int
208lec_open(struct net_device *dev)
209{
210 struct lec_priv *priv = (struct lec_priv *)dev->priv;
211
212 netif_start_queue(dev);
213 memset(&priv->stats,0,sizeof(struct net_device_stats));
214
215 return 0;
216}
217
218static __inline__ void
219lec_send(struct atm_vcc *vcc, struct sk_buff *skb, struct lec_priv *priv)
220{
221 ATM_SKB(skb)->vcc = vcc;
222 ATM_SKB(skb)->atm_options = vcc->atm_options;
223
224 atomic_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
225 if (vcc->send(vcc, skb) < 0) {
226 priv->stats.tx_dropped++;
227 return;
228 }
229
230 priv->stats.tx_packets++;
231 priv->stats.tx_bytes += skb->len;
232}
233
234static void
235lec_tx_timeout(struct net_device *dev)
236{
237 printk(KERN_INFO "%s: tx timeout\n", dev->name);
238 dev->trans_start = jiffies;
239 netif_wake_queue(dev);
240}
241
242static int
243lec_start_xmit(struct sk_buff *skb, struct net_device *dev)
244{
245 struct sk_buff *skb2;
246 struct lec_priv *priv = (struct lec_priv *)dev->priv;
247 struct lecdatahdr_8023 *lec_h;
248 struct atm_vcc *vcc;
249 struct lec_arp_table *entry;
250 unsigned char *dst;
251 int min_frame_size;
252#ifdef CONFIG_TR
253 unsigned char rdesc[ETH_ALEN]; /* Token Ring route descriptor */
254#endif
255 int is_rdesc;
256#if DUMP_PACKETS > 0
257 char buf[300];
258 int i=0;
259#endif /* DUMP_PACKETS >0 */
260
261 DPRINTK("lec_start_xmit called\n");
262 if (!priv->lecd) {
263 printk("%s:No lecd attached\n",dev->name);
264 priv->stats.tx_errors++;
265 netif_stop_queue(dev);
266 return -EUNATCH;
267 }
268
269 DPRINTK("skbuff head:%lx data:%lx tail:%lx end:%lx\n",
270 (long)skb->head, (long)skb->data, (long)skb->tail,
271 (long)skb->end);
272#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
273 if (memcmp(skb->data, bridge_ula_lec, sizeof(bridge_ula_lec)) == 0)
274 lec_handle_bridge(skb, dev);
275#endif
276
277 /* Make sure we have room for lec_id */
278 if (skb_headroom(skb) < 2) {
279
280 DPRINTK("lec_start_xmit: reallocating skb\n");
281 skb2 = skb_realloc_headroom(skb, LEC_HEADER_LEN);
282 kfree_skb(skb);
283 if (skb2 == NULL) return 0;
284 skb = skb2;
285 }
286 skb_push(skb, 2);
287
288 /* Put le header to place, works for TokenRing too */
289 lec_h = (struct lecdatahdr_8023*)skb->data;
290 lec_h->le_header = htons(priv->lecid);
291
292#ifdef CONFIG_TR
293 /* Ugly. Use this to realign Token Ring packets for
294 * e.g. PCA-200E driver. */
295 if (priv->is_trdev) {
296 skb2 = skb_realloc_headroom(skb, LEC_HEADER_LEN);
297 kfree_skb(skb);
298 if (skb2 == NULL) return 0;
299 skb = skb2;
300 }
301#endif
302
303#if DUMP_PACKETS > 0
304 printk("%s: send datalen:%ld lecid:%4.4x\n", dev->name,
305 skb->len, priv->lecid);
306#if DUMP_PACKETS >= 2
307 for(i=0;i<skb->len && i <99;i++) {
308 sprintf(buf+i*3,"%2.2x ",0xff&skb->data[i]);
309 }
310#elif DUMP_PACKETS >= 1
311 for(i=0;i<skb->len && i < 30;i++) {
312 sprintf(buf+i*3,"%2.2x ", 0xff&skb->data[i]);
313 }
314#endif /* DUMP_PACKETS >= 1 */
315 if (i==skb->len)
316 printk("%s\n",buf);
317 else
318 printk("%s...\n",buf);
319#endif /* DUMP_PACKETS > 0 */
320
321 /* Minimum ethernet-frame size */
322#ifdef CONFIG_TR
323 if (priv->is_trdev)
324 min_frame_size = LEC_MINIMUM_8025_SIZE;
325 else
326#endif
327 min_frame_size = LEC_MINIMUM_8023_SIZE;
328 if (skb->len < min_frame_size) {
329 if ((skb->len + skb_tailroom(skb)) < min_frame_size) {
330 skb2 = skb_copy_expand(skb, 0,
331 min_frame_size - skb->truesize, GFP_ATOMIC);
332 dev_kfree_skb(skb);
333 if (skb2 == NULL) {
334 priv->stats.tx_dropped++;
335 return 0;
336 }
337 skb = skb2;
338 }
339 skb_put(skb, min_frame_size - skb->len);
340 }
341
342 /* Send to right vcc */
343 is_rdesc = 0;
344 dst = lec_h->h_dest;
345#ifdef CONFIG_TR
346 if (priv->is_trdev) {
347 dst = get_tr_dst(skb->data+2, rdesc);
348 if (dst == NULL) {
349 dst = rdesc;
350 is_rdesc = 1;
351 }
352 }
353#endif
354 entry = NULL;
355 vcc = lec_arp_resolve(priv, dst, is_rdesc, &entry);
356 DPRINTK("%s:vcc:%p vcc_flags:%x, entry:%p\n", dev->name,
357 vcc, vcc?vcc->flags:0, entry);
358 if (!vcc || !test_bit(ATM_VF_READY,&vcc->flags)) {
359 if (entry && (entry->tx_wait.qlen < LEC_UNRES_QUE_LEN)) {
360 DPRINTK("%s:lec_start_xmit: queuing packet, ", dev->name);
361 DPRINTK("MAC address 0x%02x:%02x:%02x:%02x:%02x:%02x\n",
362 lec_h->h_dest[0], lec_h->h_dest[1], lec_h->h_dest[2],
363 lec_h->h_dest[3], lec_h->h_dest[4], lec_h->h_dest[5]);
364 skb_queue_tail(&entry->tx_wait, skb);
365 } else {
366 DPRINTK("%s:lec_start_xmit: tx queue full or no arp entry, dropping, ", dev->name);
367 DPRINTK("MAC address 0x%02x:%02x:%02x:%02x:%02x:%02x\n",
368 lec_h->h_dest[0], lec_h->h_dest[1], lec_h->h_dest[2],
369 lec_h->h_dest[3], lec_h->h_dest[4], lec_h->h_dest[5]);
370 priv->stats.tx_dropped++;
371 dev_kfree_skb(skb);
372 }
373 return 0;
374 }
375
376#if DUMP_PACKETS > 0
377 printk("%s:sending to vpi:%d vci:%d\n", dev->name,
378 vcc->vpi, vcc->vci);
379#endif /* DUMP_PACKETS > 0 */
380
381 while (entry && (skb2 = skb_dequeue(&entry->tx_wait))) {
382 DPRINTK("lec.c: emptying tx queue, ");
383 DPRINTK("MAC address 0x%02x:%02x:%02x:%02x:%02x:%02x\n",
384 lec_h->h_dest[0], lec_h->h_dest[1], lec_h->h_dest[2],
385 lec_h->h_dest[3], lec_h->h_dest[4], lec_h->h_dest[5]);
386 lec_send(vcc, skb2, priv);
387 }
388
389 lec_send(vcc, skb, priv);
390
391 if (!atm_may_send(vcc, 0)) {
392 struct lec_vcc_priv *vpriv = LEC_VCC_PRIV(vcc);
393
394 vpriv->xoff = 1;
395 netif_stop_queue(dev);
396
397 /*
398 * vcc->pop() might have occurred in between, making
399 * the vcc usuable again. Since xmit is serialized,
400 * this is the only situation we have to re-test.
401 */
402
403 if (atm_may_send(vcc, 0))
404 netif_wake_queue(dev);
405 }
406
407 dev->trans_start = jiffies;
408 return 0;
409}
410
411/* The inverse routine to net_open(). */
412static int
413lec_close(struct net_device *dev)
414{
415 netif_stop_queue(dev);
416 return 0;
417}
418
419/*
420 * Get the current statistics.
421 * This may be called with the card open or closed.
422 */
423static struct net_device_stats *
424lec_get_stats(struct net_device *dev)
425{
426 return &((struct lec_priv *)dev->priv)->stats;
427}
428
429static int
430lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb)
431{
432 unsigned long flags;
433 struct net_device *dev = (struct net_device*)vcc->proto_data;
434 struct lec_priv *priv = (struct lec_priv*)dev->priv;
435 struct atmlec_msg *mesg;
436 struct lec_arp_table *entry;
437 int i;
438 char *tmp; /* FIXME */
439
440 atomic_sub(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
441 mesg = (struct atmlec_msg *)skb->data;
442 tmp = skb->data;
443 tmp += sizeof(struct atmlec_msg);
444 DPRINTK("%s: msg from zeppelin:%d\n", dev->name, mesg->type);
445 switch(mesg->type) {
446 case l_set_mac_addr:
447 for (i=0;i<6;i++) {
448 dev->dev_addr[i] = mesg->content.normal.mac_addr[i];
449 }
450 break;
451 case l_del_mac_addr:
452 for(i=0;i<6;i++) {
453 dev->dev_addr[i] = 0;
454 }
455 break;
456 case l_addr_delete:
457 lec_addr_delete(priv, mesg->content.normal.atm_addr,
458 mesg->content.normal.flag);
459 break;
460 case l_topology_change:
461 priv->topology_change = mesg->content.normal.flag;
462 break;
463 case l_flush_complete:
464 lec_flush_complete(priv, mesg->content.normal.flag);
465 break;
466 case l_narp_req: /* LANE2: see 7.1.35 in the lane2 spec */
467 spin_lock_irqsave(&priv->lec_arp_lock, flags);
468 entry = lec_arp_find(priv, mesg->content.normal.mac_addr);
469 lec_arp_remove(priv, entry);
470 spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
471
472 if (mesg->content.normal.no_source_le_narp)
473 break;
474 /* FALL THROUGH */
475 case l_arp_update:
476 lec_arp_update(priv, mesg->content.normal.mac_addr,
477 mesg->content.normal.atm_addr,
478 mesg->content.normal.flag,
479 mesg->content.normal.targetless_le_arp);
480 DPRINTK("lec: in l_arp_update\n");
481 if (mesg->sizeoftlvs != 0) { /* LANE2 3.1.5 */
482 DPRINTK("lec: LANE2 3.1.5, got tlvs, size %d\n", mesg->sizeoftlvs);
483 lane2_associate_ind(dev,
484 mesg->content.normal.mac_addr,
485 tmp, mesg->sizeoftlvs);
486 }
487 break;
488 case l_config:
489 priv->maximum_unknown_frame_count =
490 mesg->content.config.maximum_unknown_frame_count;
491 priv->max_unknown_frame_time =
492 (mesg->content.config.max_unknown_frame_time*HZ);
493 priv->max_retry_count =
494 mesg->content.config.max_retry_count;
495 priv->aging_time = (mesg->content.config.aging_time*HZ);
496 priv->forward_delay_time =
497 (mesg->content.config.forward_delay_time*HZ);
498 priv->arp_response_time =
499 (mesg->content.config.arp_response_time*HZ);
500 priv->flush_timeout = (mesg->content.config.flush_timeout*HZ);
501 priv->path_switching_delay =
502 (mesg->content.config.path_switching_delay*HZ);
503 priv->lane_version = mesg->content.config.lane_version; /* LANE2 */
504 priv->lane2_ops = NULL;
505 if (priv->lane_version > 1)
506 priv->lane2_ops = &lane2_ops;
507 if (dev->change_mtu(dev, mesg->content.config.mtu))
508 printk("%s: change_mtu to %d failed\n", dev->name,
509 mesg->content.config.mtu);
510 priv->is_proxy = mesg->content.config.is_proxy;
511 break;
512 case l_flush_tran_id:
513 lec_set_flush_tran_id(priv, mesg->content.normal.atm_addr,
514 mesg->content.normal.flag);
515 break;
516 case l_set_lecid:
517 priv->lecid=(unsigned short)(0xffff&mesg->content.normal.flag);
518 break;
519 case l_should_bridge: {
520#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
521 struct net_bridge_fdb_entry *f;
522
523 DPRINTK("%s: bridge zeppelin asks about 0x%02x:%02x:%02x:%02x:%02x:%02x\n",
524 dev->name,
525 mesg->content.proxy.mac_addr[0], mesg->content.proxy.mac_addr[1],
526 mesg->content.proxy.mac_addr[2], mesg->content.proxy.mac_addr[3],
527 mesg->content.proxy.mac_addr[4], mesg->content.proxy.mac_addr[5]);
528
529 if (br_fdb_get_hook == NULL || dev->br_port == NULL)
530 break;
531
532 f = br_fdb_get_hook(dev->br_port->br, mesg->content.proxy.mac_addr);
533 if (f != NULL &&
534 f->dst->dev != dev &&
535 f->dst->state == BR_STATE_FORWARDING) {
536 /* hit from bridge table, send LE_ARP_RESPONSE */
537 struct sk_buff *skb2;
538 struct sock *sk;
539
540 DPRINTK("%s: entry found, responding to zeppelin\n", dev->name);
541 skb2 = alloc_skb(sizeof(struct atmlec_msg), GFP_ATOMIC);
542 if (skb2 == NULL) {
543 br_fdb_put_hook(f);
544 break;
545 }
546 skb2->len = sizeof(struct atmlec_msg);
547 memcpy(skb2->data, mesg, sizeof(struct atmlec_msg));
548 atm_force_charge(priv->lecd, skb2->truesize);
549 sk = sk_atm(priv->lecd);
550 skb_queue_tail(&sk->sk_receive_queue, skb2);
551 sk->sk_data_ready(sk, skb2->len);
552 }
553 if (f != NULL) br_fdb_put_hook(f);
554#endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */
555 }
556 break;
557 default:
558 printk("%s: Unknown message type %d\n", dev->name, mesg->type);
559 dev_kfree_skb(skb);
560 return -EINVAL;
561 }
562 dev_kfree_skb(skb);
563 return 0;
564}
565
566static void
567lec_atm_close(struct atm_vcc *vcc)
568{
569 struct sk_buff *skb;
570 struct net_device *dev = (struct net_device *)vcc->proto_data;
571 struct lec_priv *priv = (struct lec_priv *)dev->priv;
572
573 priv->lecd = NULL;
574 /* Do something needful? */
575
576 netif_stop_queue(dev);
577 lec_arp_destroy(priv);
578
579 if (skb_peek(&sk_atm(vcc)->sk_receive_queue))
580 printk("%s lec_atm_close: closing with messages pending\n",
581 dev->name);
582 while ((skb = skb_dequeue(&sk_atm(vcc)->sk_receive_queue)) != NULL) {
583 atm_return(vcc, skb->truesize);
584 dev_kfree_skb(skb);
585 }
586
587 printk("%s: Shut down!\n", dev->name);
588 module_put(THIS_MODULE);
589}
590
591static struct atmdev_ops lecdev_ops = {
592 .close = lec_atm_close,
593 .send = lec_atm_send
594};
595
596static struct atm_dev lecatm_dev = {
597 .ops = &lecdev_ops,
598 .type = "lec",
599 .number = 999, /* dummy device number */
600 .lock = SPIN_LOCK_UNLOCKED
601};
602
603/*
604 * LANE2: new argument struct sk_buff *data contains
605 * the LE_ARP based TLVs introduced in the LANE2 spec
606 */
607static int
608send_to_lecd(struct lec_priv *priv, atmlec_msg_type type,
609 unsigned char *mac_addr, unsigned char *atm_addr,
610 struct sk_buff *data)
611{
612 struct sock *sk;
613 struct sk_buff *skb;
614 struct atmlec_msg *mesg;
615
616 if (!priv || !priv->lecd) {
617 return -1;
618 }
619 skb = alloc_skb(sizeof(struct atmlec_msg), GFP_ATOMIC);
620 if (!skb)
621 return -1;
622 skb->len = sizeof(struct atmlec_msg);
623 mesg = (struct atmlec_msg *)skb->data;
624 memset(mesg, 0, sizeof(struct atmlec_msg));
625 mesg->type = type;
626 if (data != NULL)
627 mesg->sizeoftlvs = data->len;
628 if (mac_addr)
629 memcpy(&mesg->content.normal.mac_addr, mac_addr, ETH_ALEN);
630 else
631 mesg->content.normal.targetless_le_arp = 1;
632 if (atm_addr)
633 memcpy(&mesg->content.normal.atm_addr, atm_addr, ATM_ESA_LEN);
634
635 atm_force_charge(priv->lecd, skb->truesize);
636 sk = sk_atm(priv->lecd);
637 skb_queue_tail(&sk->sk_receive_queue, skb);
638 sk->sk_data_ready(sk, skb->len);
639
640 if (data != NULL) {
641 DPRINTK("lec: about to send %d bytes of data\n", data->len);
642 atm_force_charge(priv->lecd, data->truesize);
643 skb_queue_tail(&sk->sk_receive_queue, data);
644 sk->sk_data_ready(sk, skb->len);
645 }
646
647 return 0;
648}
649
650/* shamelessly stolen from drivers/net/net_init.c */
651static int lec_change_mtu(struct net_device *dev, int new_mtu)
652{
653 if ((new_mtu < 68) || (new_mtu > 18190))
654 return -EINVAL;
655 dev->mtu = new_mtu;
656 return 0;
657}
658
659static void lec_set_multicast_list(struct net_device *dev)
660{
661 /* by default, all multicast frames arrive over the bus.
662 * eventually support selective multicast service
663 */
664 return;
665}
666
667static void
668lec_init(struct net_device *dev)
669{
670 dev->change_mtu = lec_change_mtu;
671 dev->open = lec_open;
672 dev->stop = lec_close;
673 dev->hard_start_xmit = lec_start_xmit;
674 dev->tx_timeout = lec_tx_timeout;
675
676 dev->get_stats = lec_get_stats;
677 dev->set_multicast_list = lec_set_multicast_list;
678 dev->do_ioctl = NULL;
679 printk("%s: Initialized!\n",dev->name);
680 return;
681}
682
683static unsigned char lec_ctrl_magic[] = {
684 0xff,
685 0x00,
686 0x01,
687 0x01 };
688
689static void
690lec_push(struct atm_vcc *vcc, struct sk_buff *skb)
691{
692 struct net_device *dev = (struct net_device *)vcc->proto_data;
693 struct lec_priv *priv = (struct lec_priv *)dev->priv;
694
695#if DUMP_PACKETS >0
696 int i=0;
697 char buf[300];
698
699 printk("%s: lec_push vcc vpi:%d vci:%d\n", dev->name,
700 vcc->vpi, vcc->vci);
701#endif
702 if (!skb) {
703 DPRINTK("%s: null skb\n",dev->name);
704 lec_vcc_close(priv, vcc);
705 return;
706 }
707#if DUMP_PACKETS > 0
708 printk("%s: rcv datalen:%ld lecid:%4.4x\n", dev->name,
709 skb->len, priv->lecid);
710#if DUMP_PACKETS >= 2
711 for(i=0;i<skb->len && i <99;i++) {
712 sprintf(buf+i*3,"%2.2x ",0xff&skb->data[i]);
713 }
714#elif DUMP_PACKETS >= 1
715 for(i=0;i<skb->len && i < 30;i++) {
716 sprintf(buf+i*3,"%2.2x ", 0xff&skb->data[i]);
717 }
718#endif /* DUMP_PACKETS >= 1 */
719 if (i==skb->len)
720 printk("%s\n",buf);
721 else
722 printk("%s...\n",buf);
723#endif /* DUMP_PACKETS > 0 */
724 if (memcmp(skb->data, lec_ctrl_magic, 4) ==0) { /* Control frame, to daemon*/
725 struct sock *sk = sk_atm(vcc);
726
727 DPRINTK("%s: To daemon\n",dev->name);
728 skb_queue_tail(&sk->sk_receive_queue, skb);
729 sk->sk_data_ready(sk, skb->len);
730 } else { /* Data frame, queue to protocol handlers */
731 unsigned char *dst;
732
733 atm_return(vcc,skb->truesize);
734 if (*(uint16_t *)skb->data == htons(priv->lecid) ||
735 !priv->lecd ||
736 !(dev->flags & IFF_UP)) {
737 /* Probably looping back, or if lecd is missing,
738 lecd has gone down */
739 DPRINTK("Ignoring frame...\n");
740 dev_kfree_skb(skb);
741 return;
742 }
743#ifdef CONFIG_TR
744 if (priv->is_trdev) dst = ((struct lecdatahdr_8025 *)skb->data)->h_dest;
745 else
746#endif
747 dst = ((struct lecdatahdr_8023 *)skb->data)->h_dest;
748
749 if (!(dst[0]&0x01) && /* Never filter Multi/Broadcast */
750 !priv->is_proxy && /* Proxy wants all the packets */
751 memcmp(dst, dev->dev_addr, dev->addr_len)) {
752 dev_kfree_skb(skb);
753 return;
754 }
755 if (priv->lec_arp_empty_ones) {
756 lec_arp_check_empties(priv, vcc, skb);
757 }
758 skb->dev = dev;
759 skb_pull(skb, 2); /* skip lec_id */
760#ifdef CONFIG_TR
761 if (priv->is_trdev) skb->protocol = tr_type_trans(skb, dev);
762 else
763#endif
764 skb->protocol = eth_type_trans(skb, dev);
765 priv->stats.rx_packets++;
766 priv->stats.rx_bytes += skb->len;
767 memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data));
768 netif_rx(skb);
769 }
770}
771
772static void
773lec_pop(struct atm_vcc *vcc, struct sk_buff *skb)
774{
775 struct lec_vcc_priv *vpriv = LEC_VCC_PRIV(vcc);
776 struct net_device *dev = skb->dev;
777
778 if (vpriv == NULL) {
779 printk("lec_pop(): vpriv = NULL!?!?!?\n");
780 return;
781 }
782
783 vpriv->old_pop(vcc, skb);
784
785 if (vpriv->xoff && atm_may_send(vcc, 0)) {
786 vpriv->xoff = 0;
787 if (netif_running(dev) && netif_queue_stopped(dev))
788 netif_wake_queue(dev);
789 }
790}
791
792static int
793lec_vcc_attach(struct atm_vcc *vcc, void __user *arg)
794{
795 struct lec_vcc_priv *vpriv;
796 int bytes_left;
797 struct atmlec_ioc ioc_data;
798
799 /* Lecd must be up in this case */
800 bytes_left = copy_from_user(&ioc_data, arg, sizeof(struct atmlec_ioc));
801 if (bytes_left != 0) {
802 printk("lec: lec_vcc_attach, copy from user failed for %d bytes\n",
803 bytes_left);
804 }
805 if (ioc_data.dev_num < 0 || ioc_data.dev_num >= MAX_LEC_ITF ||
806 !dev_lec[ioc_data.dev_num])
807 return -EINVAL;
808 if (!(vpriv = kmalloc(sizeof(struct lec_vcc_priv), GFP_KERNEL)))
809 return -ENOMEM;
810 vpriv->xoff = 0;
811 vpriv->old_pop = vcc->pop;
812 vcc->user_back = vpriv;
813 vcc->pop = lec_pop;
814 lec_vcc_added(dev_lec[ioc_data.dev_num]->priv,
815 &ioc_data, vcc, vcc->push);
816 vcc->proto_data = dev_lec[ioc_data.dev_num];
817 vcc->push = lec_push;
818 return 0;
819}
820
821static int
822lec_mcast_attach(struct atm_vcc *vcc, int arg)
823{
824 if (arg <0 || arg >= MAX_LEC_ITF || !dev_lec[arg])
825 return -EINVAL;
826 vcc->proto_data = dev_lec[arg];
827 return (lec_mcast_make((struct lec_priv*)dev_lec[arg]->priv, vcc));
828}
829
830/* Initialize device. */
831static int
832lecd_attach(struct atm_vcc *vcc, int arg)
833{
834 int i;
835 struct lec_priv *priv;
836
837 if (arg<0)
838 i = 0;
839 else
840 i = arg;
841#ifdef CONFIG_TR
842 if (arg >= MAX_LEC_ITF)
843 return -EINVAL;
844#else /* Reserve the top NUM_TR_DEVS for TR */
845 if (arg >= (MAX_LEC_ITF-NUM_TR_DEVS))
846 return -EINVAL;
847#endif
848 if (!dev_lec[i]) {
849 int is_trdev, size;
850
851 is_trdev = 0;
852 if (i >= (MAX_LEC_ITF - NUM_TR_DEVS))
853 is_trdev = 1;
854
855 size = sizeof(struct lec_priv);
856#ifdef CONFIG_TR
857 if (is_trdev)
858 dev_lec[i] = alloc_trdev(size);
859 else
860#endif
861 dev_lec[i] = alloc_etherdev(size);
862 if (!dev_lec[i])
863 return -ENOMEM;
864 snprintf(dev_lec[i]->name, IFNAMSIZ, "lec%d", i);
865 if (register_netdev(dev_lec[i])) {
866 free_netdev(dev_lec[i]);
867 return -EINVAL;
868 }
869
870 priv = dev_lec[i]->priv;
871 priv->is_trdev = is_trdev;
872 lec_init(dev_lec[i]);
873 } else {
874 priv = dev_lec[i]->priv;
875 if (priv->lecd)
876 return -EADDRINUSE;
877 }
878 lec_arp_init(priv);
879 priv->itfnum = i; /* LANE2 addition */
880 priv->lecd = vcc;
881 vcc->dev = &lecatm_dev;
882 vcc_insert_socket(sk_atm(vcc));
883
884 vcc->proto_data = dev_lec[i];
885 set_bit(ATM_VF_META,&vcc->flags);
886 set_bit(ATM_VF_READY,&vcc->flags);
887
888 /* Set default values to these variables */
889 priv->maximum_unknown_frame_count = 1;
890 priv->max_unknown_frame_time = (1*HZ);
891 priv->vcc_timeout_period = (1200*HZ);
892 priv->max_retry_count = 1;
893 priv->aging_time = (300*HZ);
894 priv->forward_delay_time = (15*HZ);
895 priv->topology_change = 0;
896 priv->arp_response_time = (1*HZ);
897 priv->flush_timeout = (4*HZ);
898 priv->path_switching_delay = (6*HZ);
899
900 if (dev_lec[i]->flags & IFF_UP) {
901 netif_start_queue(dev_lec[i]);
902 }
903 __module_get(THIS_MODULE);
904 return i;
905}
906
907#ifdef CONFIG_PROC_FS
908static char* lec_arp_get_status_string(unsigned char status)
909{
910 static char *lec_arp_status_string[] = {
911 "ESI_UNKNOWN ",
912 "ESI_ARP_PENDING ",
913 "ESI_VC_PENDING ",
914 "<Undefined> ",
915 "ESI_FLUSH_PENDING ",
916 "ESI_FORWARD_DIRECT"
917 };
918
919 if (status > ESI_FORWARD_DIRECT)
920 status = 3; /* ESI_UNDEFINED */
921 return lec_arp_status_string[status];
922}
923
924static void lec_info(struct seq_file *seq, struct lec_arp_table *entry)
925{
926 int i;
927
928 for (i = 0; i < ETH_ALEN; i++)
929 seq_printf(seq, "%2.2x", entry->mac_addr[i] & 0xff);
930 seq_printf(seq, " ");
931 for (i = 0; i < ATM_ESA_LEN; i++)
932 seq_printf(seq, "%2.2x", entry->atm_addr[i] & 0xff);
933 seq_printf(seq, " %s %4.4x", lec_arp_get_status_string(entry->status),
934 entry->flags & 0xffff);
935 if (entry->vcc)
936 seq_printf(seq, "%3d %3d ", entry->vcc->vpi, entry->vcc->vci);
937 else
938 seq_printf(seq, " ");
939 if (entry->recv_vcc) {
940 seq_printf(seq, " %3d %3d", entry->recv_vcc->vpi,
941 entry->recv_vcc->vci);
942 }
943 seq_putc(seq, '\n');
944}
945
946
947struct lec_state {
948 unsigned long flags;
949 struct lec_priv *locked;
950 struct lec_arp_table *entry;
951 struct net_device *dev;
952 int itf;
953 int arp_table;
954 int misc_table;
955};
956
957static void *lec_tbl_walk(struct lec_state *state, struct lec_arp_table *tbl,
958 loff_t *l)
959{
960 struct lec_arp_table *e = state->entry;
961
962 if (!e)
963 e = tbl;
964 if (e == (void *)1) {
965 e = tbl;
966 --*l;
967 }
968 for (; e; e = e->next) {
969 if (--*l < 0)
970 break;
971 }
972 state->entry = e;
973 return (*l < 0) ? state : NULL;
974}
975
976static void *lec_arp_walk(struct lec_state *state, loff_t *l,
977 struct lec_priv *priv)
978{
979 void *v = NULL;
980 int p;
981
982 for (p = state->arp_table; p < LEC_ARP_TABLE_SIZE; p++) {
983 v = lec_tbl_walk(state, priv->lec_arp_tables[p], l);
984 if (v)
985 break;
986 }
987 state->arp_table = p;
988 return v;
989}
990
991static void *lec_misc_walk(struct lec_state *state, loff_t *l,
992 struct lec_priv *priv)
993{
994 struct lec_arp_table *lec_misc_tables[] = {
995 priv->lec_arp_empty_ones,
996 priv->lec_no_forward,
997 priv->mcast_fwds
998 };
999 void *v = NULL;
1000 int q;
1001
1002 for (q = state->misc_table; q < ARRAY_SIZE(lec_misc_tables); q++) {
1003 v = lec_tbl_walk(state, lec_misc_tables[q], l);
1004 if (v)
1005 break;
1006 }
1007 state->misc_table = q;
1008 return v;
1009}
1010
1011static void *lec_priv_walk(struct lec_state *state, loff_t *l,
1012 struct lec_priv *priv)
1013{
1014 if (!state->locked) {
1015 state->locked = priv;
1016 spin_lock_irqsave(&priv->lec_arp_lock, state->flags);
1017 }
1018 if (!lec_arp_walk(state, l, priv) &&
1019 !lec_misc_walk(state, l, priv)) {
1020 spin_unlock_irqrestore(&priv->lec_arp_lock, state->flags);
1021 state->locked = NULL;
1022 /* Partial state reset for the next time we get called */
1023 state->arp_table = state->misc_table = 0;
1024 }
1025 return state->locked;
1026}
1027
1028static void *lec_itf_walk(struct lec_state *state, loff_t *l)
1029{
1030 struct net_device *dev;
1031 void *v;
1032
1033 dev = state->dev ? state->dev : dev_lec[state->itf];
1034 v = (dev && dev->priv) ? lec_priv_walk(state, l, dev->priv) : NULL;
1035 if (!v && dev) {
1036 dev_put(dev);
1037 /* Partial state reset for the next time we get called */
1038 dev = NULL;
1039 }
1040 state->dev = dev;
1041 return v;
1042}
1043
1044static void *lec_get_idx(struct lec_state *state, loff_t l)
1045{
1046 void *v = NULL;
1047
1048 for (; state->itf < MAX_LEC_ITF; state->itf++) {
1049 v = lec_itf_walk(state, &l);
1050 if (v)
1051 break;
1052 }
1053 return v;
1054}
1055
1056static void *lec_seq_start(struct seq_file *seq, loff_t *pos)
1057{
1058 struct lec_state *state = seq->private;
1059
1060 state->itf = 0;
1061 state->dev = NULL;
1062 state->locked = NULL;
1063 state->arp_table = 0;
1064 state->misc_table = 0;
1065 state->entry = (void *)1;
1066
1067 return *pos ? lec_get_idx(state, *pos) : (void*)1;
1068}
1069
1070static void lec_seq_stop(struct seq_file *seq, void *v)
1071{
1072 struct lec_state *state = seq->private;
1073
1074 if (state->dev) {
1075 spin_unlock_irqrestore(&state->locked->lec_arp_lock,
1076 state->flags);
1077 dev_put(state->dev);
1078 }
1079}
1080
1081static void *lec_seq_next(struct seq_file *seq, void *v, loff_t *pos)
1082{
1083 struct lec_state *state = seq->private;
1084
1085 v = lec_get_idx(state, 1);
1086 *pos += !!PTR_ERR(v);
1087 return v;
1088}
1089
1090static int lec_seq_show(struct seq_file *seq, void *v)
1091{
1092 static char lec_banner[] = "Itf MAC ATM destination"
1093 " Status Flags "
1094 "VPI/VCI Recv VPI/VCI\n";
1095
1096 if (v == (void *)1)
1097 seq_puts(seq, lec_banner);
1098 else {
1099 struct lec_state *state = seq->private;
1100 struct net_device *dev = state->dev;
1101
1102 seq_printf(seq, "%s ", dev->name);
1103 lec_info(seq, state->entry);
1104 }
1105 return 0;
1106}
1107
1108static struct seq_operations lec_seq_ops = {
1109 .start = lec_seq_start,
1110 .next = lec_seq_next,
1111 .stop = lec_seq_stop,
1112 .show = lec_seq_show,
1113};
1114
1115static int lec_seq_open(struct inode *inode, struct file *file)
1116{
1117 struct lec_state *state;
1118 struct seq_file *seq;
1119 int rc = -EAGAIN;
1120
1121 state = kmalloc(sizeof(*state), GFP_KERNEL);
1122 if (!state) {
1123 rc = -ENOMEM;
1124 goto out;
1125 }
1126
1127 rc = seq_open(file, &lec_seq_ops);
1128 if (rc)
1129 goto out_kfree;
1130 seq = file->private_data;
1131 seq->private = state;
1132out:
1133 return rc;
1134
1135out_kfree:
1136 kfree(state);
1137 goto out;
1138}
1139
1140static int lec_seq_release(struct inode *inode, struct file *file)
1141{
1142 return seq_release_private(inode, file);
1143}
1144
1145static struct file_operations lec_seq_fops = {
1146 .owner = THIS_MODULE,
1147 .open = lec_seq_open,
1148 .read = seq_read,
1149 .llseek = seq_lseek,
1150 .release = lec_seq_release,
1151};
1152#endif
1153
1154static int lane_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
1155{
1156 struct atm_vcc *vcc = ATM_SD(sock);
1157 int err = 0;
1158
1159 switch (cmd) {
1160 case ATMLEC_CTRL:
1161 case ATMLEC_MCAST:
1162 case ATMLEC_DATA:
1163 if (!capable(CAP_NET_ADMIN))
1164 return -EPERM;
1165 break;
1166 default:
1167 return -ENOIOCTLCMD;
1168 }
1169
1170 switch (cmd) {
1171 case ATMLEC_CTRL:
1172 err = lecd_attach(vcc, (int) arg);
1173 if (err >= 0)
1174 sock->state = SS_CONNECTED;
1175 break;
1176 case ATMLEC_MCAST:
1177 err = lec_mcast_attach(vcc, (int) arg);
1178 break;
1179 case ATMLEC_DATA:
1180 err = lec_vcc_attach(vcc, (void __user *) arg);
1181 break;
1182 }
1183
1184 return err;
1185}
1186
1187static struct atm_ioctl lane_ioctl_ops = {
1188 .owner = THIS_MODULE,
1189 .ioctl = lane_ioctl,
1190};
1191
1192static int __init lane_module_init(void)
1193{
1194#ifdef CONFIG_PROC_FS
1195 struct proc_dir_entry *p;
1196
1197 p = create_proc_entry("lec", S_IRUGO, atm_proc_root);
1198 if (p)
1199 p->proc_fops = &lec_seq_fops;
1200#endif
1201
1202 register_atm_ioctl(&lane_ioctl_ops);
1203 printk("lec.c: " __DATE__ " " __TIME__ " initialized\n");
1204 return 0;
1205}
1206
1207static void __exit lane_module_cleanup(void)
1208{
1209 int i;
1210 struct lec_priv *priv;
1211
1212 remove_proc_entry("lec", atm_proc_root);
1213
1214 deregister_atm_ioctl(&lane_ioctl_ops);
1215
1216 for (i = 0; i < MAX_LEC_ITF; i++) {
1217 if (dev_lec[i] != NULL) {
1218 priv = (struct lec_priv *)dev_lec[i]->priv;
1219 unregister_netdev(dev_lec[i]);
1220 free_netdev(dev_lec[i]);
1221 dev_lec[i] = NULL;
1222 }
1223 }
1224
1225 return;
1226}
1227
1228module_init(lane_module_init);
1229module_exit(lane_module_cleanup);
1230
1231/*
1232 * LANE2: 3.1.3, LE_RESOLVE.request
1233 * Non force allocates memory and fills in *tlvs, fills in *sizeoftlvs.
1234 * If sizeoftlvs == NULL the default TLVs associated with with this
1235 * lec will be used.
1236 * If dst_mac == NULL, targetless LE_ARP will be sent
1237 */
1238static int lane2_resolve(struct net_device *dev, u8 *dst_mac, int force,
1239 u8 **tlvs, u32 *sizeoftlvs)
1240{
1241 unsigned long flags;
1242 struct lec_priv *priv = (struct lec_priv *)dev->priv;
1243 struct lec_arp_table *table;
1244 struct sk_buff *skb;
1245 int retval;
1246
1247 if (force == 0) {
1248 spin_lock_irqsave(&priv->lec_arp_lock, flags);
1249 table = lec_arp_find(priv, dst_mac);
1250 spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
1251 if(table == NULL)
1252 return -1;
1253
1254 *tlvs = kmalloc(table->sizeoftlvs, GFP_ATOMIC);
1255 if (*tlvs == NULL)
1256 return -1;
1257
1258 memcpy(*tlvs, table->tlvs, table->sizeoftlvs);
1259 *sizeoftlvs = table->sizeoftlvs;
1260
1261 return 0;
1262 }
1263
1264 if (sizeoftlvs == NULL)
1265 retval = send_to_lecd(priv, l_arp_xmt, dst_mac, NULL, NULL);
1266
1267 else {
1268 skb = alloc_skb(*sizeoftlvs, GFP_ATOMIC);
1269 if (skb == NULL)
1270 return -1;
1271 skb->len = *sizeoftlvs;
1272 memcpy(skb->data, *tlvs, *sizeoftlvs);
1273 retval = send_to_lecd(priv, l_arp_xmt, dst_mac, NULL, skb);
1274 }
1275 return retval;
1276}
1277
1278
1279/*
1280 * LANE2: 3.1.4, LE_ASSOCIATE.request
1281 * Associate the *tlvs with the *lan_dst address.
1282 * Will overwrite any previous association
1283 * Returns 1 for success, 0 for failure (out of memory)
1284 *
1285 */
1286static int lane2_associate_req (struct net_device *dev, u8 *lan_dst,
1287 u8 *tlvs, u32 sizeoftlvs)
1288{
1289 int retval;
1290 struct sk_buff *skb;
1291 struct lec_priv *priv = (struct lec_priv*)dev->priv;
1292
1293 if ( memcmp(lan_dst, dev->dev_addr, ETH_ALEN) != 0 )
1294 return (0); /* not our mac address */
1295
1296 kfree(priv->tlvs); /* NULL if there was no previous association */
1297
1298 priv->tlvs = kmalloc(sizeoftlvs, GFP_KERNEL);
1299 if (priv->tlvs == NULL)
1300 return (0);
1301 priv->sizeoftlvs = sizeoftlvs;
1302 memcpy(priv->tlvs, tlvs, sizeoftlvs);
1303
1304 skb = alloc_skb(sizeoftlvs, GFP_ATOMIC);
1305 if (skb == NULL)
1306 return 0;
1307 skb->len = sizeoftlvs;
1308 memcpy(skb->data, tlvs, sizeoftlvs);
1309 retval = send_to_lecd(priv, l_associate_req, NULL, NULL, skb);
1310 if (retval != 0)
1311 printk("lec.c: lane2_associate_req() failed\n");
1312 /* If the previous association has changed we must
1313 * somehow notify other LANE entities about the change
1314 */
1315 return (1);
1316}
1317
1318/*
1319 * LANE2: 3.1.5, LE_ASSOCIATE.indication
1320 *
1321 */
1322static void lane2_associate_ind (struct net_device *dev, u8 *mac_addr,
1323 u8 *tlvs, u32 sizeoftlvs)
1324{
1325#if 0
1326 int i = 0;
1327#endif
1328 struct lec_priv *priv = (struct lec_priv *)dev->priv;
1329#if 0 /* Why have the TLVs in LE_ARP entries since we do not use them? When you
1330 uncomment this code, make sure the TLVs get freed when entry is killed */
1331 struct lec_arp_table *entry = lec_arp_find(priv, mac_addr);
1332
1333 if (entry == NULL)
1334 return; /* should not happen */
1335
1336 kfree(entry->tlvs);
1337
1338 entry->tlvs = kmalloc(sizeoftlvs, GFP_KERNEL);
1339 if (entry->tlvs == NULL)
1340 return;
1341
1342 entry->sizeoftlvs = sizeoftlvs;
1343 memcpy(entry->tlvs, tlvs, sizeoftlvs);
1344#endif
1345#if 0
1346 printk("lec.c: lane2_associate_ind()\n");
1347 printk("dump of tlvs, sizeoftlvs=%d\n", sizeoftlvs);
1348 while (i < sizeoftlvs)
1349 printk("%02x ", tlvs[i++]);
1350
1351 printk("\n");
1352#endif
1353
1354 /* tell MPOA about the TLVs we saw */
1355 if (priv->lane2_ops && priv->lane2_ops->associate_indicator) {
1356 priv->lane2_ops->associate_indicator(dev, mac_addr,
1357 tlvs, sizeoftlvs);
1358 }
1359 return;
1360}
1361
1362/*
1363 * Here starts what used to lec_arpc.c
1364 *
1365 * lec_arpc.c was added here when making
1366 * lane client modular. October 1997
1367 *
1368 */
1369
1370#include <linux/types.h>
1371#include <linux/sched.h>
1372#include <linux/timer.h>
1373#include <asm/param.h>
1374#include <asm/atomic.h>
1375#include <linux/inetdevice.h>
1376#include <net/route.h>
1377
1378
1379#if 0
1380#define DPRINTK(format,args...)
1381/*
1382#define DPRINTK printk
1383*/
1384#endif
1385#define DEBUG_ARP_TABLE 0
1386
1387#define LEC_ARP_REFRESH_INTERVAL (3*HZ)
1388
1389static void lec_arp_check_expire(unsigned long data);
1390static void lec_arp_expire_arp(unsigned long data);
1391
1392/*
1393 * Arp table funcs
1394 */
1395
1396#define HASH(ch) (ch & (LEC_ARP_TABLE_SIZE -1))
1397
1398/*
1399 * Initialization of arp-cache
1400 */
1401static void
1402lec_arp_init(struct lec_priv *priv)
1403{
1404 unsigned short i;
1405
1406 for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
1407 priv->lec_arp_tables[i] = NULL;
1408 }
1409 spin_lock_init(&priv->lec_arp_lock);
1410 init_timer(&priv->lec_arp_timer);
1411 priv->lec_arp_timer.expires = jiffies + LEC_ARP_REFRESH_INTERVAL;
1412 priv->lec_arp_timer.data = (unsigned long)priv;
1413 priv->lec_arp_timer.function = lec_arp_check_expire;
1414 add_timer(&priv->lec_arp_timer);
1415}
1416
1417static void
1418lec_arp_clear_vccs(struct lec_arp_table *entry)
1419{
1420 if (entry->vcc) {
1421 struct atm_vcc *vcc = entry->vcc;
1422 struct lec_vcc_priv *vpriv = LEC_VCC_PRIV(vcc);
1423 struct net_device *dev = (struct net_device*) vcc->proto_data;
1424
1425 vcc->pop = vpriv->old_pop;
1426 if (vpriv->xoff)
1427 netif_wake_queue(dev);
1428 kfree(vpriv);
1429 vcc->user_back = NULL;
1430 vcc->push = entry->old_push;
1431 vcc_release_async(vcc, -EPIPE);
1432 vcc = NULL;
1433 }
1434 if (entry->recv_vcc) {
1435 entry->recv_vcc->push = entry->old_recv_push;
1436 vcc_release_async(entry->recv_vcc, -EPIPE);
1437 entry->recv_vcc = NULL;
1438 }
1439}
1440
1441/*
1442 * Insert entry to lec_arp_table
1443 * LANE2: Add to the end of the list to satisfy 8.1.13
1444 */
1445static inline void
1446lec_arp_add(struct lec_priv *priv, struct lec_arp_table *to_add)
1447{
1448 unsigned short place;
1449 struct lec_arp_table *tmp;
1450
1451 place = HASH(to_add->mac_addr[ETH_ALEN-1]);
1452 tmp = priv->lec_arp_tables[place];
1453 to_add->next = NULL;
1454 if (tmp == NULL)
1455 priv->lec_arp_tables[place] = to_add;
1456
1457 else { /* add to the end */
1458 while (tmp->next)
1459 tmp = tmp->next;
1460 tmp->next = to_add;
1461 }
1462
1463 DPRINTK("LEC_ARP: Added entry:%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n",
1464 0xff&to_add->mac_addr[0], 0xff&to_add->mac_addr[1],
1465 0xff&to_add->mac_addr[2], 0xff&to_add->mac_addr[3],
1466 0xff&to_add->mac_addr[4], 0xff&to_add->mac_addr[5]);
1467}
1468
1469/*
1470 * Remove entry from lec_arp_table
1471 */
1472static int
1473lec_arp_remove(struct lec_priv *priv,
1474 struct lec_arp_table *to_remove)
1475{
1476 unsigned short place;
1477 struct lec_arp_table *tmp;
1478 int remove_vcc=1;
1479
1480 if (!to_remove) {
1481 return -1;
1482 }
1483 place = HASH(to_remove->mac_addr[ETH_ALEN-1]);
1484 tmp = priv->lec_arp_tables[place];
1485 if (tmp == to_remove) {
1486 priv->lec_arp_tables[place] = tmp->next;
1487 } else {
1488 while(tmp && tmp->next != to_remove) {
1489 tmp = tmp->next;
1490 }
1491 if (!tmp) {/* Entry was not found */
1492 return -1;
1493 }
1494 }
1495 tmp->next = to_remove->next;
1496 del_timer(&to_remove->timer);
1497
1498 /* If this is the only MAC connected to this VCC, also tear down
1499 the VCC */
1500 if (to_remove->status >= ESI_FLUSH_PENDING) {
1501 /*
1502 * ESI_FLUSH_PENDING, ESI_FORWARD_DIRECT
1503 */
1504 for(place = 0; place < LEC_ARP_TABLE_SIZE; place++) {
1505 for(tmp = priv->lec_arp_tables[place]; tmp != NULL; tmp = tmp->next) {
1506 if (memcmp(tmp->atm_addr, to_remove->atm_addr,
1507 ATM_ESA_LEN)==0) {
1508 remove_vcc=0;
1509 break;
1510 }
1511 }
1512 }
1513 if (remove_vcc)
1514 lec_arp_clear_vccs(to_remove);
1515 }
1516 skb_queue_purge(&to_remove->tx_wait); /* FIXME: good place for this? */
1517
1518 DPRINTK("LEC_ARP: Removed entry:%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n",
1519 0xff&to_remove->mac_addr[0], 0xff&to_remove->mac_addr[1],
1520 0xff&to_remove->mac_addr[2], 0xff&to_remove->mac_addr[3],
1521 0xff&to_remove->mac_addr[4], 0xff&to_remove->mac_addr[5]);
1522 return 0;
1523}
1524
1525#if DEBUG_ARP_TABLE
1526static char*
1527get_status_string(unsigned char st)
1528{
1529 switch(st) {
1530 case ESI_UNKNOWN:
1531 return "ESI_UNKNOWN";
1532 case ESI_ARP_PENDING:
1533 return "ESI_ARP_PENDING";
1534 case ESI_VC_PENDING:
1535 return "ESI_VC_PENDING";
1536 case ESI_FLUSH_PENDING:
1537 return "ESI_FLUSH_PENDING";
1538 case ESI_FORWARD_DIRECT:
1539 return "ESI_FORWARD_DIRECT";
1540 default:
1541 return "<UNKNOWN>";
1542 }
1543}
1544#endif
1545
1546static void
1547dump_arp_table(struct lec_priv *priv)
1548{
1549#if DEBUG_ARP_TABLE
1550 int i,j, offset;
1551 struct lec_arp_table *rulla;
1552 char buf[1024];
1553 struct lec_arp_table **lec_arp_tables =
1554 (struct lec_arp_table **)priv->lec_arp_tables;
1555 struct lec_arp_table *lec_arp_empty_ones =
1556 (struct lec_arp_table *)priv->lec_arp_empty_ones;
1557 struct lec_arp_table *lec_no_forward =
1558 (struct lec_arp_table *)priv->lec_no_forward;
1559 struct lec_arp_table *mcast_fwds = priv->mcast_fwds;
1560
1561
1562 printk("Dump %p:\n",priv);
1563 for (i=0;i<LEC_ARP_TABLE_SIZE;i++) {
1564 rulla = lec_arp_tables[i];
1565 offset = 0;
1566 offset += sprintf(buf,"%d: %p\n",i, rulla);
1567 while (rulla) {
1568 offset += sprintf(buf+offset,"Mac:");
1569 for(j=0;j<ETH_ALEN;j++) {
1570 offset+=sprintf(buf+offset,
1571 "%2.2x ",
1572 rulla->mac_addr[j]&0xff);
1573 }
1574 offset +=sprintf(buf+offset,"Atm:");
1575 for(j=0;j<ATM_ESA_LEN;j++) {
1576 offset+=sprintf(buf+offset,
1577 "%2.2x ",
1578 rulla->atm_addr[j]&0xff);
1579 }
1580 offset+=sprintf(buf+offset,
1581 "Vcc vpi:%d vci:%d, Recv_vcc vpi:%d vci:%d Last_used:%lx, Timestamp:%lx, No_tries:%d ",
1582 rulla->vcc?rulla->vcc->vpi:0,
1583 rulla->vcc?rulla->vcc->vci:0,
1584 rulla->recv_vcc?rulla->recv_vcc->vpi:0,
1585 rulla->recv_vcc?rulla->recv_vcc->vci:0,
1586 rulla->last_used,
1587 rulla->timestamp, rulla->no_tries);
1588 offset+=sprintf(buf+offset,
1589 "Flags:%x, Packets_flooded:%x, Status: %s ",
1590 rulla->flags, rulla->packets_flooded,
1591 get_status_string(rulla->status));
1592 offset+=sprintf(buf+offset,"->%p\n",rulla->next);
1593 rulla = rulla->next;
1594 }
1595 printk("%s",buf);
1596 }
1597 rulla = lec_no_forward;
1598 if (rulla)
1599 printk("No forward\n");
1600 while(rulla) {
1601 offset=0;
1602 offset += sprintf(buf+offset,"Mac:");
1603 for(j=0;j<ETH_ALEN;j++) {
1604 offset+=sprintf(buf+offset,"%2.2x ",
1605 rulla->mac_addr[j]&0xff);
1606 }
1607 offset +=sprintf(buf+offset,"Atm:");
1608 for(j=0;j<ATM_ESA_LEN;j++) {
1609 offset+=sprintf(buf+offset,"%2.2x ",
1610 rulla->atm_addr[j]&0xff);
1611 }
1612 offset+=sprintf(buf+offset,
1613 "Vcc vpi:%d vci:%d, Recv_vcc vpi:%d vci:%d Last_used:%lx, Timestamp:%lx, No_tries:%d ",
1614 rulla->vcc?rulla->vcc->vpi:0,
1615 rulla->vcc?rulla->vcc->vci:0,
1616 rulla->recv_vcc?rulla->recv_vcc->vpi:0,
1617 rulla->recv_vcc?rulla->recv_vcc->vci:0,
1618 rulla->last_used,
1619 rulla->timestamp, rulla->no_tries);
1620 offset+=sprintf(buf+offset,
1621 "Flags:%x, Packets_flooded:%x, Status: %s ",
1622 rulla->flags, rulla->packets_flooded,
1623 get_status_string(rulla->status));
1624 offset+=sprintf(buf+offset,"->%lx\n",(long)rulla->next);
1625 rulla = rulla->next;
1626 printk("%s",buf);
1627 }
1628 rulla = lec_arp_empty_ones;
1629 if (rulla)
1630 printk("Empty ones\n");
1631 while(rulla) {
1632 offset=0;
1633 offset += sprintf(buf+offset,"Mac:");
1634 for(j=0;j<ETH_ALEN;j++) {
1635 offset+=sprintf(buf+offset,"%2.2x ",
1636 rulla->mac_addr[j]&0xff);
1637 }
1638 offset +=sprintf(buf+offset,"Atm:");
1639 for(j=0;j<ATM_ESA_LEN;j++) {
1640 offset+=sprintf(buf+offset,"%2.2x ",
1641 rulla->atm_addr[j]&0xff);
1642 }
1643 offset+=sprintf(buf+offset,
1644 "Vcc vpi:%d vci:%d, Recv_vcc vpi:%d vci:%d Last_used:%lx, Timestamp:%lx, No_tries:%d ",
1645 rulla->vcc?rulla->vcc->vpi:0,
1646 rulla->vcc?rulla->vcc->vci:0,
1647 rulla->recv_vcc?rulla->recv_vcc->vpi:0,
1648 rulla->recv_vcc?rulla->recv_vcc->vci:0,
1649 rulla->last_used,
1650 rulla->timestamp, rulla->no_tries);
1651 offset+=sprintf(buf+offset,
1652 "Flags:%x, Packets_flooded:%x, Status: %s ",
1653 rulla->flags, rulla->packets_flooded,
1654 get_status_string(rulla->status));
1655 offset+=sprintf(buf+offset,"->%lx\n",(long)rulla->next);
1656 rulla = rulla->next;
1657 printk("%s",buf);
1658 }
1659
1660 rulla = mcast_fwds;
1661 if (rulla)
1662 printk("Multicast Forward VCCs\n");
1663 while(rulla) {
1664 offset=0;
1665 offset += sprintf(buf+offset,"Mac:");
1666 for(j=0;j<ETH_ALEN;j++) {
1667 offset+=sprintf(buf+offset,"%2.2x ",
1668 rulla->mac_addr[j]&0xff);
1669 }
1670 offset +=sprintf(buf+offset,"Atm:");
1671 for(j=0;j<ATM_ESA_LEN;j++) {
1672 offset+=sprintf(buf+offset,"%2.2x ",
1673 rulla->atm_addr[j]&0xff);
1674 }
1675 offset+=sprintf(buf+offset,
1676 "Vcc vpi:%d vci:%d, Recv_vcc vpi:%d vci:%d Last_used:%lx, Timestamp:%lx, No_tries:%d ",
1677 rulla->vcc?rulla->vcc->vpi:0,
1678 rulla->vcc?rulla->vcc->vci:0,
1679 rulla->recv_vcc?rulla->recv_vcc->vpi:0,
1680 rulla->recv_vcc?rulla->recv_vcc->vci:0,
1681 rulla->last_used,
1682 rulla->timestamp, rulla->no_tries);
1683 offset+=sprintf(buf+offset,
1684 "Flags:%x, Packets_flooded:%x, Status: %s ",
1685 rulla->flags, rulla->packets_flooded,
1686 get_status_string(rulla->status));
1687 offset+=sprintf(buf+offset,"->%lx\n",(long)rulla->next);
1688 rulla = rulla->next;
1689 printk("%s",buf);
1690 }
1691
1692#endif
1693}
1694
1695/*
1696 * Destruction of arp-cache
1697 */
1698static void
1699lec_arp_destroy(struct lec_priv *priv)
1700{
1701 unsigned long flags;
1702 struct lec_arp_table *entry, *next;
1703 int i;
1704
1705 del_timer_sync(&priv->lec_arp_timer);
1706
1707 /*
1708 * Remove all entries
1709 */
1710
1711 spin_lock_irqsave(&priv->lec_arp_lock, flags);
1712 for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
1713 for(entry = priv->lec_arp_tables[i]; entry != NULL; entry=next) {
1714 next = entry->next;
1715 lec_arp_remove(priv, entry);
1716 kfree(entry);
1717 }
1718 }
1719 entry = priv->lec_arp_empty_ones;
1720 while(entry) {
1721 next = entry->next;
1722 del_timer_sync(&entry->timer);
1723 lec_arp_clear_vccs(entry);
1724 kfree(entry);
1725 entry = next;
1726 }
1727 priv->lec_arp_empty_ones = NULL;
1728 entry = priv->lec_no_forward;
1729 while(entry) {
1730 next = entry->next;
1731 del_timer_sync(&entry->timer);
1732 lec_arp_clear_vccs(entry);
1733 kfree(entry);
1734 entry = next;
1735 }
1736 priv->lec_no_forward = NULL;
1737 entry = priv->mcast_fwds;
1738 while(entry) {
1739 next = entry->next;
1740 /* No timer, LANEv2 7.1.20 and 2.3.5.3 */
1741 lec_arp_clear_vccs(entry);
1742 kfree(entry);
1743 entry = next;
1744 }
1745 priv->mcast_fwds = NULL;
1746 priv->mcast_vcc = NULL;
1747 memset(priv->lec_arp_tables, 0,
1748 sizeof(struct lec_arp_table *) * LEC_ARP_TABLE_SIZE);
1749 spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
1750}
1751
1752
1753/*
1754 * Find entry by mac_address
1755 */
1756static struct lec_arp_table*
1757lec_arp_find(struct lec_priv *priv,
1758 unsigned char *mac_addr)
1759{
1760 unsigned short place;
1761 struct lec_arp_table *to_return;
1762
1763 DPRINTK("LEC_ARP: lec_arp_find :%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n",
1764 mac_addr[0]&0xff, mac_addr[1]&0xff, mac_addr[2]&0xff,
1765 mac_addr[3]&0xff, mac_addr[4]&0xff, mac_addr[5]&0xff);
1766 place = HASH(mac_addr[ETH_ALEN-1]);
1767
1768 to_return = priv->lec_arp_tables[place];
1769 while(to_return) {
1770 if (memcmp(mac_addr, to_return->mac_addr, ETH_ALEN) == 0) {
1771 return to_return;
1772 }
1773 to_return = to_return->next;
1774 }
1775 return NULL;
1776}
1777
1778static struct lec_arp_table*
1779make_entry(struct lec_priv *priv, unsigned char *mac_addr)
1780{
1781 struct lec_arp_table *to_return;
1782
1783 to_return = (struct lec_arp_table *) kmalloc(sizeof(struct lec_arp_table),
1784 GFP_ATOMIC);
1785 if (!to_return) {
1786 printk("LEC: Arp entry kmalloc failed\n");
1787 return NULL;
1788 }
1789 memset(to_return, 0, sizeof(struct lec_arp_table));
1790 memcpy(to_return->mac_addr, mac_addr, ETH_ALEN);
1791 init_timer(&to_return->timer);
1792 to_return->timer.function = lec_arp_expire_arp;
1793 to_return->timer.data = (unsigned long) to_return;
1794 to_return->last_used = jiffies;
1795 to_return->priv = priv;
1796 skb_queue_head_init(&to_return->tx_wait);
1797 return to_return;
1798}
1799
1800/*
1801 *
1802 * Arp sent timer expired
1803 *
1804 */
1805static void
1806lec_arp_expire_arp(unsigned long data)
1807{
1808 struct lec_arp_table *entry;
1809
1810 entry = (struct lec_arp_table *)data;
1811
1812 DPRINTK("lec_arp_expire_arp\n");
1813 if (entry->status == ESI_ARP_PENDING) {
1814 if (entry->no_tries <= entry->priv->max_retry_count) {
1815 if (entry->is_rdesc)
1816 send_to_lecd(entry->priv, l_rdesc_arp_xmt, entry->mac_addr, NULL, NULL);
1817 else
1818 send_to_lecd(entry->priv, l_arp_xmt, entry->mac_addr, NULL, NULL);
1819 entry->no_tries++;
1820 }
1821 mod_timer(&entry->timer, jiffies + (1*HZ));
1822 }
1823}
1824
1825/*
1826 *
1827 * Unknown/unused vcc expire, remove associated entry
1828 *
1829 */
1830static void
1831lec_arp_expire_vcc(unsigned long data)
1832{
1833 unsigned long flags;
1834 struct lec_arp_table *to_remove = (struct lec_arp_table*)data;
1835 struct lec_priv *priv = (struct lec_priv *)to_remove->priv;
1836 struct lec_arp_table *entry = NULL;
1837
1838 del_timer(&to_remove->timer);
1839
1840 DPRINTK("LEC_ARP %p %p: lec_arp_expire_vcc vpi:%d vci:%d\n",
1841 to_remove, priv,
1842 to_remove->vcc?to_remove->recv_vcc->vpi:0,
1843 to_remove->vcc?to_remove->recv_vcc->vci:0);
1844 DPRINTK("eo:%p nf:%p\n",priv->lec_arp_empty_ones,priv->lec_no_forward);
1845
1846 spin_lock_irqsave(&priv->lec_arp_lock, flags);
1847 if (to_remove == priv->lec_arp_empty_ones)
1848 priv->lec_arp_empty_ones = to_remove->next;
1849 else {
1850 entry = priv->lec_arp_empty_ones;
1851 while (entry && entry->next != to_remove)
1852 entry = entry->next;
1853 if (entry)
1854 entry->next = to_remove->next;
1855 }
1856 if (!entry) {
1857 if (to_remove == priv->lec_no_forward) {
1858 priv->lec_no_forward = to_remove->next;
1859 } else {
1860 entry = priv->lec_no_forward;
1861 while (entry && entry->next != to_remove)
1862 entry = entry->next;
1863 if (entry)
1864 entry->next = to_remove->next;
1865 }
1866 }
1867 spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
1868
1869 lec_arp_clear_vccs(to_remove);
1870 kfree(to_remove);
1871}
1872
1873/*
1874 * Expire entries.
1875 * 1. Re-set timer
1876 * 2. For each entry, delete entries that have aged past the age limit.
1877 * 3. For each entry, depending on the status of the entry, perform
1878 * the following maintenance.
1879 * a. If status is ESI_VC_PENDING or ESI_ARP_PENDING then if the
1880 * tick_count is above the max_unknown_frame_time, clear
1881 * the tick_count to zero and clear the packets_flooded counter
1882 * to zero. This supports the packet rate limit per address
1883 * while flooding unknowns.
1884 * b. If the status is ESI_FLUSH_PENDING and the tick_count is greater
1885 * than or equal to the path_switching_delay, change the status
1886 * to ESI_FORWARD_DIRECT. This causes the flush period to end
1887 * regardless of the progress of the flush protocol.
1888 */
1889static void
1890lec_arp_check_expire(unsigned long data)
1891{
1892 unsigned long flags;
1893 struct lec_priv *priv = (struct lec_priv *)data;
1894 struct lec_arp_table *entry, *next;
1895 unsigned long now;
1896 unsigned long time_to_check;
1897 int i;
1898
1899 DPRINTK("lec_arp_check_expire %p\n",priv);
1900 DPRINTK("expire: eo:%p nf:%p\n",priv->lec_arp_empty_ones,
1901 priv->lec_no_forward);
1902 now = jiffies;
1903 spin_lock_irqsave(&priv->lec_arp_lock, flags);
1904 for(i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
1905 for(entry = priv->lec_arp_tables[i]; entry != NULL; ) {
1906 if ((entry->flags) & LEC_REMOTE_FLAG &&
1907 priv->topology_change)
1908 time_to_check = priv->forward_delay_time;
1909 else
1910 time_to_check = priv->aging_time;
1911
1912 DPRINTK("About to expire: %lx - %lx > %lx\n",
1913 now,entry->last_used, time_to_check);
1914 if( time_after(now, entry->last_used+
1915 time_to_check) &&
1916 !(entry->flags & LEC_PERMANENT_FLAG) &&
1917 !(entry->mac_addr[0] & 0x01) ) { /* LANE2: 7.1.20 */
1918 /* Remove entry */
1919 DPRINTK("LEC:Entry timed out\n");
1920 next = entry->next;
1921 lec_arp_remove(priv, entry);
1922 kfree(entry);
1923 entry = next;
1924 } else {
1925 /* Something else */
1926 if ((entry->status == ESI_VC_PENDING ||
1927 entry->status == ESI_ARP_PENDING)
1928 && time_after_eq(now,
1929 entry->timestamp +
1930 priv->max_unknown_frame_time)) {
1931 entry->timestamp = jiffies;
1932 entry->packets_flooded = 0;
1933 if (entry->status == ESI_VC_PENDING)
1934 send_to_lecd(priv, l_svc_setup, entry->mac_addr, entry->atm_addr, NULL);
1935 }
1936 if (entry->status == ESI_FLUSH_PENDING
1937 &&
1938 time_after_eq(now, entry->timestamp+
1939 priv->path_switching_delay)) {
1940 struct sk_buff *skb;
1941
1942 while ((skb = skb_dequeue(&entry->tx_wait)) != NULL)
1943 lec_send(entry->vcc, skb, entry->priv);
1944 entry->last_used = jiffies;
1945 entry->status =
1946 ESI_FORWARD_DIRECT;
1947 }
1948 entry = entry->next;
1949 }
1950 }
1951 }
1952 spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
1953
1954 mod_timer(&priv->lec_arp_timer, jiffies + LEC_ARP_REFRESH_INTERVAL);
1955}
1956/*
1957 * Try to find vcc where mac_address is attached.
1958 *
1959 */
1960static struct atm_vcc*
1961lec_arp_resolve(struct lec_priv *priv, unsigned char *mac_to_find,
1962 int is_rdesc, struct lec_arp_table **ret_entry)
1963{
1964 unsigned long flags;
1965 struct lec_arp_table *entry;
1966 struct atm_vcc *found;
1967
1968 if (mac_to_find[0] & 0x01) {
1969 switch (priv->lane_version) {
1970 case 1:
1971 return priv->mcast_vcc;
1972 break;
1973 case 2: /* LANE2 wants arp for multicast addresses */
1974 if ( memcmp(mac_to_find, bus_mac, ETH_ALEN) == 0)
1975 return priv->mcast_vcc;
1976 break;
1977 default:
1978 break;
1979 }
1980 }
1981
1982 spin_lock_irqsave(&priv->lec_arp_lock, flags);
1983 entry = lec_arp_find(priv, mac_to_find);
1984
1985 if (entry) {
1986 if (entry->status == ESI_FORWARD_DIRECT) {
1987 /* Connection Ok */
1988 entry->last_used = jiffies;
1989 *ret_entry = entry;
1990 found = entry->vcc;
1991 goto out;
1992 }
1993 /* Data direct VC not yet set up, check to see if the unknown
1994 frame count is greater than the limit. If the limit has
1995 not been reached, allow the caller to send packet to
1996 BUS. */
1997 if (entry->status != ESI_FLUSH_PENDING &&
1998 entry->packets_flooded<priv->maximum_unknown_frame_count) {
1999 entry->packets_flooded++;
2000 DPRINTK("LEC_ARP: Flooding..\n");
2001 found = priv->mcast_vcc;
2002 goto out;
2003 }
2004 /* We got here because entry->status == ESI_FLUSH_PENDING
2005 * or BUS flood limit was reached for an entry which is
2006 * in ESI_ARP_PENDING or ESI_VC_PENDING state.
2007 */
2008 *ret_entry = entry;
2009 DPRINTK("lec: entry->status %d entry->vcc %p\n", entry->status, entry->vcc);
2010 found = NULL;
2011 } else {
2012 /* No matching entry was found */
2013 entry = make_entry(priv, mac_to_find);
2014 DPRINTK("LEC_ARP: Making entry\n");
2015 if (!entry) {
2016 found = priv->mcast_vcc;
2017 goto out;
2018 }
2019 lec_arp_add(priv, entry);
2020 /* We want arp-request(s) to be sent */
2021 entry->packets_flooded =1;
2022 entry->status = ESI_ARP_PENDING;
2023 entry->no_tries = 1;
2024 entry->last_used = entry->timestamp = jiffies;
2025 entry->is_rdesc = is_rdesc;
2026 if (entry->is_rdesc)
2027 send_to_lecd(priv, l_rdesc_arp_xmt, mac_to_find, NULL, NULL);
2028 else
2029 send_to_lecd(priv, l_arp_xmt, mac_to_find, NULL, NULL);
2030 entry->timer.expires = jiffies + (1*HZ);
2031 entry->timer.function = lec_arp_expire_arp;
2032 add_timer(&entry->timer);
2033 found = priv->mcast_vcc;
2034 }
2035
2036out:
2037 spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
2038 return found;
2039}
2040
2041static int
2042lec_addr_delete(struct lec_priv *priv, unsigned char *atm_addr,
2043 unsigned long permanent)
2044{
2045 unsigned long flags;
2046 struct lec_arp_table *entry, *next;
2047 int i;
2048
2049 DPRINTK("lec_addr_delete\n");
2050 spin_lock_irqsave(&priv->lec_arp_lock, flags);
2051 for(i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
2052 for(entry = priv->lec_arp_tables[i]; entry != NULL; entry = next) {
2053 next = entry->next;
2054 if (!memcmp(atm_addr, entry->atm_addr, ATM_ESA_LEN)
2055 && (permanent ||
2056 !(entry->flags & LEC_PERMANENT_FLAG))) {
2057 lec_arp_remove(priv, entry);
2058 kfree(entry);
2059 }
2060 spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
2061 return 0;
2062 }
2063 }
2064 spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
2065 return -1;
2066}
2067
2068/*
2069 * Notifies: Response to arp_request (atm_addr != NULL)
2070 */
2071static void
2072lec_arp_update(struct lec_priv *priv, unsigned char *mac_addr,
2073 unsigned char *atm_addr, unsigned long remoteflag,
2074 unsigned int targetless_le_arp)
2075{
2076 unsigned long flags;
2077 struct lec_arp_table *entry, *tmp;
2078 int i;
2079
2080 DPRINTK("lec:%s", (targetless_le_arp) ? "targetless ": " ");
2081 DPRINTK("lec_arp_update mac:%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n",
2082 mac_addr[0],mac_addr[1],mac_addr[2],mac_addr[3],
2083 mac_addr[4],mac_addr[5]);
2084
2085 spin_lock_irqsave(&priv->lec_arp_lock, flags);
2086 entry = lec_arp_find(priv, mac_addr);
2087 if (entry == NULL && targetless_le_arp)
2088 goto out; /* LANE2: ignore targetless LE_ARPs for which
2089 * we have no entry in the cache. 7.1.30
2090 */
2091 if (priv->lec_arp_empty_ones) {
2092 entry = priv->lec_arp_empty_ones;
2093 if (!memcmp(entry->atm_addr, atm_addr, ATM_ESA_LEN)) {
2094 priv->lec_arp_empty_ones = entry->next;
2095 } else {
2096 while(entry->next && memcmp(entry->next->atm_addr,
2097 atm_addr, ATM_ESA_LEN))
2098 entry = entry->next;
2099 if (entry->next) {
2100 tmp = entry;
2101 entry = entry->next;
2102 tmp->next = entry->next;
2103 } else
2104 entry = NULL;
2105
2106 }
2107 if (entry) {
2108 del_timer(&entry->timer);
2109 tmp = lec_arp_find(priv, mac_addr);
2110 if (tmp) {
2111 del_timer(&tmp->timer);
2112 tmp->status = ESI_FORWARD_DIRECT;
2113 memcpy(tmp->atm_addr, atm_addr, ATM_ESA_LEN);
2114 tmp->vcc = entry->vcc;
2115 tmp->old_push = entry->old_push;
2116 tmp->last_used = jiffies;
2117 del_timer(&entry->timer);
2118 kfree(entry);
2119 entry=tmp;
2120 } else {
2121 entry->status = ESI_FORWARD_DIRECT;
2122 memcpy(entry->mac_addr, mac_addr, ETH_ALEN);
2123 entry->last_used = jiffies;
2124 lec_arp_add(priv, entry);
2125 }
2126 if (remoteflag)
2127 entry->flags|=LEC_REMOTE_FLAG;
2128 else
2129 entry->flags&=~LEC_REMOTE_FLAG;
2130 DPRINTK("After update\n");
2131 dump_arp_table(priv);
2132 goto out;
2133 }
2134 }
2135 entry = lec_arp_find(priv, mac_addr);
2136 if (!entry) {
2137 entry = make_entry(priv, mac_addr);
2138 if (!entry)
2139 goto out;
2140 entry->status = ESI_UNKNOWN;
2141 lec_arp_add(priv, entry);
2142 /* Temporary, changes before end of function */
2143 }
2144 memcpy(entry->atm_addr, atm_addr, ATM_ESA_LEN);
2145 del_timer(&entry->timer);
2146 for(i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
2147 for(tmp = priv->lec_arp_tables[i]; tmp; tmp=tmp->next) {
2148 if (entry != tmp &&
2149 !memcmp(tmp->atm_addr, atm_addr,
2150 ATM_ESA_LEN)) {
2151 /* Vcc to this host exists */
2152 if (tmp->status > ESI_VC_PENDING) {
2153 /*
2154 * ESI_FLUSH_PENDING,
2155 * ESI_FORWARD_DIRECT
2156 */
2157 entry->vcc = tmp->vcc;
2158 entry->old_push=tmp->old_push;
2159 }
2160 entry->status=tmp->status;
2161 break;
2162 }
2163 }
2164 }
2165 if (remoteflag)
2166 entry->flags|=LEC_REMOTE_FLAG;
2167 else
2168 entry->flags&=~LEC_REMOTE_FLAG;
2169 if (entry->status == ESI_ARP_PENDING ||
2170 entry->status == ESI_UNKNOWN) {
2171 entry->status = ESI_VC_PENDING;
2172 send_to_lecd(priv, l_svc_setup, entry->mac_addr, atm_addr, NULL);
2173 }
2174 DPRINTK("After update2\n");
2175 dump_arp_table(priv);
2176out:
2177 spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
2178}
2179
2180/*
2181 * Notifies: Vcc setup ready
2182 */
2183static void
2184lec_vcc_added(struct lec_priv *priv, struct atmlec_ioc *ioc_data,
2185 struct atm_vcc *vcc,
2186 void (*old_push)(struct atm_vcc *vcc, struct sk_buff *skb))
2187{
2188 unsigned long flags;
2189 struct lec_arp_table *entry;
2190 int i, found_entry=0;
2191
2192 spin_lock_irqsave(&priv->lec_arp_lock, flags);
2193 if (ioc_data->receive == 2) {
2194 /* Vcc for Multicast Forward. No timer, LANEv2 7.1.20 and 2.3.5.3 */
2195
2196 DPRINTK("LEC_ARP: Attaching mcast forward\n");
2197#if 0
2198 entry = lec_arp_find(priv, bus_mac);
2199 if (!entry) {
2200 printk("LEC_ARP: Multicast entry not found!\n");
2201 goto out;
2202 }
2203 memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);
2204 entry->recv_vcc = vcc;
2205 entry->old_recv_push = old_push;
2206#endif
2207 entry = make_entry(priv, bus_mac);
2208 if (entry == NULL)
2209 goto out;
2210 del_timer(&entry->timer);
2211 memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);
2212 entry->recv_vcc = vcc;
2213 entry->old_recv_push = old_push;
2214 entry->next = priv->mcast_fwds;
2215 priv->mcast_fwds = entry;
2216 goto out;
2217 } else if (ioc_data->receive == 1) {
2218 /* Vcc which we don't want to make default vcc, attach it
2219 anyway. */
2220 DPRINTK("LEC_ARP:Attaching data direct, not default :%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n",
2221 ioc_data->atm_addr[0],ioc_data->atm_addr[1],
2222 ioc_data->atm_addr[2],ioc_data->atm_addr[3],
2223 ioc_data->atm_addr[4],ioc_data->atm_addr[5],
2224 ioc_data->atm_addr[6],ioc_data->atm_addr[7],
2225 ioc_data->atm_addr[8],ioc_data->atm_addr[9],
2226 ioc_data->atm_addr[10],ioc_data->atm_addr[11],
2227 ioc_data->atm_addr[12],ioc_data->atm_addr[13],
2228 ioc_data->atm_addr[14],ioc_data->atm_addr[15],
2229 ioc_data->atm_addr[16],ioc_data->atm_addr[17],
2230 ioc_data->atm_addr[18],ioc_data->atm_addr[19]);
2231 entry = make_entry(priv, bus_mac);
2232 if (entry == NULL)
2233 goto out;
2234 memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);
2235 memset(entry->mac_addr, 0, ETH_ALEN);
2236 entry->recv_vcc = vcc;
2237 entry->old_recv_push = old_push;
2238 entry->status = ESI_UNKNOWN;
2239 entry->timer.expires = jiffies + priv->vcc_timeout_period;
2240 entry->timer.function = lec_arp_expire_vcc;
2241 add_timer(&entry->timer);
2242 entry->next = priv->lec_no_forward;
2243 priv->lec_no_forward = entry;
2244 dump_arp_table(priv);
2245 goto out;
2246 }
2247 DPRINTK("LEC_ARP:Attaching data direct, default:%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n",
2248 ioc_data->atm_addr[0],ioc_data->atm_addr[1],
2249 ioc_data->atm_addr[2],ioc_data->atm_addr[3],
2250 ioc_data->atm_addr[4],ioc_data->atm_addr[5],
2251 ioc_data->atm_addr[6],ioc_data->atm_addr[7],
2252 ioc_data->atm_addr[8],ioc_data->atm_addr[9],
2253 ioc_data->atm_addr[10],ioc_data->atm_addr[11],
2254 ioc_data->atm_addr[12],ioc_data->atm_addr[13],
2255 ioc_data->atm_addr[14],ioc_data->atm_addr[15],
2256 ioc_data->atm_addr[16],ioc_data->atm_addr[17],
2257 ioc_data->atm_addr[18],ioc_data->atm_addr[19]);
2258 for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
2259 for (entry = priv->lec_arp_tables[i]; entry; entry=entry->next) {
2260 if (memcmp(ioc_data->atm_addr, entry->atm_addr,
2261 ATM_ESA_LEN)==0) {
2262 DPRINTK("LEC_ARP: Attaching data direct\n");
2263 DPRINTK("Currently -> Vcc: %d, Rvcc:%d\n",
2264 entry->vcc?entry->vcc->vci:0,
2265 entry->recv_vcc?entry->recv_vcc->vci:0);
2266 found_entry=1;
2267 del_timer(&entry->timer);
2268 entry->vcc = vcc;
2269 entry->old_push = old_push;
2270 if (entry->status == ESI_VC_PENDING) {
2271 if(priv->maximum_unknown_frame_count
2272 ==0)
2273 entry->status =
2274 ESI_FORWARD_DIRECT;
2275 else {
2276 entry->timestamp = jiffies;
2277 entry->status =
2278 ESI_FLUSH_PENDING;
2279#if 0
2280 send_to_lecd(priv,l_flush_xmt,
2281 NULL,
2282 entry->atm_addr,
2283 NULL);
2284#endif
2285 }
2286 } else {
2287 /* They were forming a connection
2288 to us, and we to them. Our
2289 ATM address is numerically lower
2290 than theirs, so we make connection
2291 we formed into default VCC (8.1.11).
2292 Connection they made gets torn
2293 down. This might confuse some
2294 clients. Can be changed if
2295 someone reports trouble... */
2296 ;
2297 }
2298 }
2299 }
2300 }
2301 if (found_entry) {
2302 DPRINTK("After vcc was added\n");
2303 dump_arp_table(priv);
2304 goto out;
2305 }
2306 /* Not found, snatch address from first data packet that arrives from
2307 this vcc */
2308 entry = make_entry(priv, bus_mac);
2309 if (!entry)
2310 goto out;
2311 entry->vcc = vcc;
2312 entry->old_push = old_push;
2313 memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);
2314 memset(entry->mac_addr, 0, ETH_ALEN);
2315 entry->status = ESI_UNKNOWN;
2316 entry->next = priv->lec_arp_empty_ones;
2317 priv->lec_arp_empty_ones = entry;
2318 entry->timer.expires = jiffies + priv->vcc_timeout_period;
2319 entry->timer.function = lec_arp_expire_vcc;
2320 add_timer(&entry->timer);
2321 DPRINTK("After vcc was added\n");
2322 dump_arp_table(priv);
2323out:
2324 spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
2325}
2326
2327static void
2328lec_flush_complete(struct lec_priv *priv, unsigned long tran_id)
2329{
2330 unsigned long flags;
2331 struct lec_arp_table *entry;
2332 int i;
2333
2334 DPRINTK("LEC:lec_flush_complete %lx\n",tran_id);
2335 spin_lock_irqsave(&priv->lec_arp_lock, flags);
2336 for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
2337 for (entry = priv->lec_arp_tables[i]; entry; entry=entry->next) {
2338 if (entry->flush_tran_id == tran_id &&
2339 entry->status == ESI_FLUSH_PENDING) {
2340 struct sk_buff *skb;
2341
2342 while ((skb = skb_dequeue(&entry->tx_wait)) != NULL)
2343 lec_send(entry->vcc, skb, entry->priv);
2344 entry->status = ESI_FORWARD_DIRECT;
2345 DPRINTK("LEC_ARP: Flushed\n");
2346 }
2347 }
2348 }
2349 spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
2350 dump_arp_table(priv);
2351}
2352
2353static void
2354lec_set_flush_tran_id(struct lec_priv *priv,
2355 unsigned char *atm_addr, unsigned long tran_id)
2356{
2357 unsigned long flags;
2358 struct lec_arp_table *entry;
2359 int i;
2360
2361 spin_lock_irqsave(&priv->lec_arp_lock, flags);
2362 for (i = 0; i < LEC_ARP_TABLE_SIZE; i++)
2363 for(entry = priv->lec_arp_tables[i]; entry; entry=entry->next)
2364 if (!memcmp(atm_addr, entry->atm_addr, ATM_ESA_LEN)) {
2365 entry->flush_tran_id = tran_id;
2366 DPRINTK("Set flush transaction id to %lx for %p\n",tran_id,entry);
2367 }
2368 spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
2369}
2370
2371static int
2372lec_mcast_make(struct lec_priv *priv, struct atm_vcc *vcc)
2373{
2374 unsigned long flags;
2375 unsigned char mac_addr[] = {
2376 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
2377 struct lec_arp_table *to_add;
2378 struct lec_vcc_priv *vpriv;
2379 int err = 0;
2380
2381 if (!(vpriv = kmalloc(sizeof(struct lec_vcc_priv), GFP_KERNEL)))
2382 return -ENOMEM;
2383 vpriv->xoff = 0;
2384 vpriv->old_pop = vcc->pop;
2385 vcc->user_back = vpriv;
2386 vcc->pop = lec_pop;
2387 spin_lock_irqsave(&priv->lec_arp_lock, flags);
2388 to_add = make_entry(priv, mac_addr);
2389 if (!to_add) {
2390 vcc->pop = vpriv->old_pop;
2391 kfree(vpriv);
2392 err = -ENOMEM;
2393 goto out;
2394 }
2395 memcpy(to_add->atm_addr, vcc->remote.sas_addr.prv, ATM_ESA_LEN);
2396 to_add->status = ESI_FORWARD_DIRECT;
2397 to_add->flags |= LEC_PERMANENT_FLAG;
2398 to_add->vcc = vcc;
2399 to_add->old_push = vcc->push;
2400 vcc->push = lec_push;
2401 priv->mcast_vcc = vcc;
2402 lec_arp_add(priv, to_add);
2403out:
2404 spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
2405 return err;
2406}
2407
2408static void
2409lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc)
2410{
2411 unsigned long flags;
2412 struct lec_arp_table *entry, *next;
2413 int i;
2414
2415 DPRINTK("LEC_ARP: lec_vcc_close vpi:%d vci:%d\n",vcc->vpi,vcc->vci);
2416 dump_arp_table(priv);
2417 spin_lock_irqsave(&priv->lec_arp_lock, flags);
2418 for(i=0;i<LEC_ARP_TABLE_SIZE;i++) {
2419 for(entry = priv->lec_arp_tables[i];entry; entry=next) {
2420 next = entry->next;
2421 if (vcc == entry->vcc) {
2422 lec_arp_remove(priv, entry);
2423 kfree(entry);
2424 if (priv->mcast_vcc == vcc) {
2425 priv->mcast_vcc = NULL;
2426 }
2427 }
2428 }
2429 }
2430
2431 entry = priv->lec_arp_empty_ones;
2432 priv->lec_arp_empty_ones = NULL;
2433 while (entry != NULL) {
2434 next = entry->next;
2435 if (entry->vcc == vcc) { /* leave it out from the list */
2436 lec_arp_clear_vccs(entry);
2437 del_timer(&entry->timer);
2438 kfree(entry);
2439 }
2440 else { /* put it back to the list */
2441 entry->next = priv->lec_arp_empty_ones;
2442 priv->lec_arp_empty_ones = entry;
2443 }
2444 entry = next;
2445 }
2446
2447 entry = priv->lec_no_forward;
2448 priv->lec_no_forward = NULL;
2449 while (entry != NULL) {
2450 next = entry->next;
2451 if (entry->recv_vcc == vcc) {
2452 lec_arp_clear_vccs(entry);
2453 del_timer(&entry->timer);
2454 kfree(entry);
2455 }
2456 else {
2457 entry->next = priv->lec_no_forward;
2458 priv->lec_no_forward = entry;
2459 }
2460 entry = next;
2461 }
2462
2463 entry = priv->mcast_fwds;
2464 priv->mcast_fwds = NULL;
2465 while (entry != NULL) {
2466 next = entry->next;
2467 if (entry->recv_vcc == vcc) {
2468 lec_arp_clear_vccs(entry);
2469 /* No timer, LANEv2 7.1.20 and 2.3.5.3 */
2470 kfree(entry);
2471 }
2472 else {
2473 entry->next = priv->mcast_fwds;
2474 priv->mcast_fwds = entry;
2475 }
2476 entry = next;
2477 }
2478
2479 spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
2480 dump_arp_table(priv);
2481}
2482
2483static void
2484lec_arp_check_empties(struct lec_priv *priv,
2485 struct atm_vcc *vcc, struct sk_buff *skb)
2486{
2487 unsigned long flags;
2488 struct lec_arp_table *entry, *prev;
2489 struct lecdatahdr_8023 *hdr = (struct lecdatahdr_8023 *)skb->data;
2490 unsigned char *src;
2491#ifdef CONFIG_TR
2492 struct lecdatahdr_8025 *tr_hdr = (struct lecdatahdr_8025 *)skb->data;
2493
2494 if (priv->is_trdev) src = tr_hdr->h_source;
2495 else
2496#endif
2497 src = hdr->h_source;
2498
2499 spin_lock_irqsave(&priv->lec_arp_lock, flags);
2500 entry = priv->lec_arp_empty_ones;
2501 if (vcc == entry->vcc) {
2502 del_timer(&entry->timer);
2503 memcpy(entry->mac_addr, src, ETH_ALEN);
2504 entry->status = ESI_FORWARD_DIRECT;
2505 entry->last_used = jiffies;
2506 priv->lec_arp_empty_ones = entry->next;
2507 /* We might have got an entry */
2508 if ((prev = lec_arp_find(priv,src))) {
2509 lec_arp_remove(priv, prev);
2510 kfree(prev);
2511 }
2512 lec_arp_add(priv, entry);
2513 goto out;
2514 }
2515 prev = entry;
2516 entry = entry->next;
2517 while (entry && entry->vcc != vcc) {
2518 prev= entry;
2519 entry = entry->next;
2520 }
2521 if (!entry) {
2522 DPRINTK("LEC_ARP: Arp_check_empties: entry not found!\n");
2523 goto out;
2524 }
2525 del_timer(&entry->timer);
2526 memcpy(entry->mac_addr, src, ETH_ALEN);
2527 entry->status = ESI_FORWARD_DIRECT;
2528 entry->last_used = jiffies;
2529 prev->next = entry->next;
2530 if ((prev = lec_arp_find(priv, src))) {
2531 lec_arp_remove(priv, prev);
2532 kfree(prev);
2533 }
2534 lec_arp_add(priv, entry);
2535out:
2536 spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
2537}
2538MODULE_LICENSE("GPL");
diff --git a/net/atm/lec.h b/net/atm/lec.h
new file mode 100644
index 000000000000..6606082b29a8
--- /dev/null
+++ b/net/atm/lec.h
@@ -0,0 +1,142 @@
1/*
2 *
3 * Lan Emulation client header file
4 *
5 * Marko Kiiskila mkiiskila@yahoo.com
6 *
7 */
8
9#ifndef _LEC_H_
10#define _LEC_H_
11
12#include <linux/config.h>
13#include <linux/atmdev.h>
14#include <linux/netdevice.h>
15#include <linux/atmlec.h>
16
17#define LEC_HEADER_LEN 16
18
19struct lecdatahdr_8023 {
20 unsigned short le_header;
21 unsigned char h_dest[ETH_ALEN];
22 unsigned char h_source[ETH_ALEN];
23 unsigned short h_type;
24};
25
26struct lecdatahdr_8025 {
27 unsigned short le_header;
28 unsigned char ac_pad;
29 unsigned char fc;
30 unsigned char h_dest[ETH_ALEN];
31 unsigned char h_source[ETH_ALEN];
32};
33
34#define LEC_MINIMUM_8023_SIZE 62
35#define LEC_MINIMUM_8025_SIZE 16
36
37/*
38 * Operations that LANE2 capable device can do. Two first functions
39 * are used to make the device do things. See spec 3.1.3 and 3.1.4.
40 *
41 * The third function is intented for the MPOA component sitting on
42 * top of the LANE device. The MPOA component assigns it's own function
43 * to (*associate_indicator)() and the LANE device will use that
44 * function to tell about TLVs it sees floating through.
45 *
46 */
47struct lane2_ops {
48 int (*resolve)(struct net_device *dev, u8 *dst_mac, int force,
49 u8 **tlvs, u32 *sizeoftlvs);
50 int (*associate_req)(struct net_device *dev, u8 *lan_dst,
51 u8 *tlvs, u32 sizeoftlvs);
52 void (*associate_indicator)(struct net_device *dev, u8 *mac_addr,
53 u8 *tlvs, u32 sizeoftlvs);
54};
55
56/*
57 * ATM LAN Emulation supports both LLC & Dix Ethernet EtherType
58 * frames.
59 * 1. Dix Ethernet EtherType frames encoded by placing EtherType
60 * field in h_type field. Data follows immediatelly after header.
61 * 2. LLC Data frames whose total length, including LLC field and data,
62 * but not padding required to meet the minimum data frame length,
63 * is less than 1536(0x0600) MUST be encoded by placing that length
64 * in the h_type field. The LLC field follows header immediatelly.
65 * 3. LLC data frames longer than this maximum MUST be encoded by placing
66 * the value 0 in the h_type field.
67 *
68 */
69
70/* Hash table size */
71#define LEC_ARP_TABLE_SIZE 16
72
73struct lec_priv {
74 struct net_device_stats stats;
75 unsigned short lecid; /* Lecid of this client */
76 struct lec_arp_table *lec_arp_empty_ones;
77 /* Used for storing VCC's that don't have a MAC address attached yet */
78 struct lec_arp_table *lec_arp_tables[LEC_ARP_TABLE_SIZE];
79 /* Actual LE ARP table */
80 struct lec_arp_table *lec_no_forward;
81 /* Used for storing VCC's (and forward packets from) which are to
82 age out by not using them to forward packets.
83 This is because to some LE clients there will be 2 VCCs. Only
84 one of them gets used. */
85 struct lec_arp_table *mcast_fwds;
86 /* With LANEv2 it is possible that BUS (or a special multicast server)
87 establishes multiple Multicast Forward VCCs to us. This list
88 collects all those VCCs. LANEv1 client has only one item in this
89 list. These entries are not aged out. */
90 spinlock_t lec_arp_lock;
91 struct atm_vcc *mcast_vcc; /* Default Multicast Send VCC */
92 struct atm_vcc *lecd;
93 struct timer_list lec_arp_timer;
94 /* C10 */
95 unsigned int maximum_unknown_frame_count;
96/* Within the period of time defined by this variable, the client will send
97 no more than C10 frames to BUS for a given unicast destination. (C11) */
98 unsigned long max_unknown_frame_time;
99/* If no traffic has been sent in this vcc for this period of time,
100 vcc will be torn down (C12)*/
101 unsigned long vcc_timeout_period;
102/* An LE Client MUST not retry an LE_ARP_REQUEST for a
103 given frame's LAN Destination more than maximum retry count times,
104 after the first LEC_ARP_REQUEST (C13)*/
105 unsigned short max_retry_count;
106/* Max time the client will maintain an entry in its arp cache in
107 absence of a verification of that relationship (C17)*/
108 unsigned long aging_time;
109/* Max time the client will maintain an entry in cache when
110 topology change flag is true (C18) */
111 unsigned long forward_delay_time;
112/* Topology change flag (C19)*/
113 int topology_change;
114/* Max time the client expects an LE_ARP_REQUEST/LE_ARP_RESPONSE
115 cycle to take (C20)*/
116 unsigned long arp_response_time;
117/* Time limit ot wait to receive an LE_FLUSH_RESPONSE after the
118 LE_FLUSH_REQUEST has been sent before taking recover action. (C21)*/
119 unsigned long flush_timeout;
120/* The time since sending a frame to the bus after which the
121 LE Client may assume that the frame has been either discarded or
122 delivered to the recipient (C22) */
123 unsigned long path_switching_delay;
124
125 u8 *tlvs; /* LANE2: TLVs are new */
126 u32 sizeoftlvs; /* The size of the tlv array in bytes */
127 int lane_version; /* LANE2 */
128 int itfnum; /* e.g. 2 for lec2, 5 for lec5 */
129 struct lane2_ops *lane2_ops; /* can be NULL for LANE v1 */
130 int is_proxy; /* bridge between ATM and Ethernet */
131 int is_trdev; /* Device type, 0 = Ethernet, 1 = TokenRing */
132};
133
134struct lec_vcc_priv {
135 void (*old_pop)(struct atm_vcc *vcc, struct sk_buff *skb);
136 int xoff;
137};
138
139#define LEC_VCC_PRIV(vcc) ((struct lec_vcc_priv *)((vcc)->user_back))
140
141#endif /* _LEC_H_ */
142
diff --git a/net/atm/lec_arpc.h b/net/atm/lec_arpc.h
new file mode 100644
index 000000000000..397448094648
--- /dev/null
+++ b/net/atm/lec_arpc.h
@@ -0,0 +1,92 @@
1/*
2 * Lec arp cache
3 * Marko Kiiskila mkiiskila@yahoo.com
4 *
5 */
6#ifndef _LEC_ARP_H
7#define _LEC_ARP_H
8#include <linux/atm.h>
9#include <linux/atmdev.h>
10#include <linux/if_ether.h>
11#include <linux/atmlec.h>
12
13struct lec_arp_table {
14 struct lec_arp_table *next; /* Linked entry list */
15 unsigned char atm_addr[ATM_ESA_LEN]; /* Atm address */
16 unsigned char mac_addr[ETH_ALEN]; /* Mac address */
17 int is_rdesc; /* Mac address is a route descriptor */
18 struct atm_vcc *vcc; /* Vcc this entry is attached */
19 struct atm_vcc *recv_vcc; /* Vcc we receive data from */
20 void (*old_push)(struct atm_vcc *vcc,struct sk_buff *skb);
21 /* Push that leads to daemon */
22 void (*old_recv_push)(struct atm_vcc *vcc, struct sk_buff *skb);
23 /* Push that leads to daemon */
24 void (*old_close)(struct atm_vcc *vcc);
25 /* We want to see when this
26 * vcc gets closed */
27 unsigned long last_used; /* For expiry */
28 unsigned long timestamp; /* Used for various timestamping
29 * things:
30 * 1. FLUSH started
31 * (status=ESI_FLUSH_PENDING)
32 * 2. Counting to
33 * max_unknown_frame_time
34 * (status=ESI_ARP_PENDING||
35 * status=ESI_VC_PENDING)
36 */
37 unsigned char no_tries; /* No of times arp retry has been
38 tried */
39 unsigned char status; /* Status of this entry */
40 unsigned short flags; /* Flags for this entry */
41 unsigned short packets_flooded; /* Data packets flooded */
42 unsigned long flush_tran_id; /* Transaction id in flush protocol */
43 struct timer_list timer; /* Arping timer */
44 struct lec_priv *priv; /* Pointer back */
45
46 u8 *tlvs; /* LANE2: Each MAC address can have TLVs */
47 u32 sizeoftlvs; /* associated with it. sizeoftlvs tells the */
48 /* the length of the tlvs array */
49 struct sk_buff_head tx_wait; /* wait queue for outgoing packets */
50};
51
52struct tlv { /* LANE2: Template tlv struct for accessing */
53 /* the tlvs in the lec_arp_table->tlvs array*/
54 u32 type;
55 u8 length;
56 u8 value[255];
57};
58
59/* Status fields */
60#define ESI_UNKNOWN 0 /*
61 * Next packet sent to this mac address
62 * causes ARP-request to be sent
63 */
64#define ESI_ARP_PENDING 1 /*
65 * There is no ATM address associated with this
66 * 48-bit address. The LE-ARP protocol is in
67 * progress.
68 */
69#define ESI_VC_PENDING 2 /*
70 * There is a valid ATM address associated with
71 * this 48-bit address but there is no VC set
72 * up to that ATM address. The signaling
73 * protocol is in process.
74 */
75#define ESI_FLUSH_PENDING 4 /*
76 * The LEC has been notified of the FLUSH_START
77 * status and it is assumed that the flush
78 * protocol is in process.
79 */
80#define ESI_FORWARD_DIRECT 5 /*
81 * Either the Path Switching Delay (C22) has
82 * elapsed or the LEC has notified the Mapping
83 * that the flush protocol has completed. In
84 * either case, it is safe to forward packets
85 * to this address via the data direct VC.
86 */
87
88/* Flag values */
89#define LEC_REMOTE_FLAG 0x0001
90#define LEC_PERMANENT_FLAG 0x0002
91
92#endif
diff --git a/net/atm/mpc.c b/net/atm/mpc.c
new file mode 100644
index 000000000000..17a81ebe7e6e
--- /dev/null
+++ b/net/atm/mpc.c
@@ -0,0 +1,1514 @@
1#include <linux/kernel.h>
2#include <linux/string.h>
3#include <linux/timer.h>
4#include <linux/init.h>
5#include <linux/bitops.h>
6#include <linux/seq_file.h>
7
8/* We are an ethernet device */
9#include <linux/if_ether.h>
10#include <linux/netdevice.h>
11#include <linux/etherdevice.h>
12#include <net/sock.h>
13#include <linux/skbuff.h>
14#include <linux/ip.h>
15#include <asm/byteorder.h>
16#include <asm/uaccess.h>
17#include <net/checksum.h> /* for ip_fast_csum() */
18#include <net/arp.h>
19#include <net/dst.h>
20#include <linux/proc_fs.h>
21
22/* And atm device */
23#include <linux/atmdev.h>
24#include <linux/atmlec.h>
25#include <linux/atmmpc.h>
26/* Modular too */
27#include <linux/config.h>
28#include <linux/module.h>
29
30#include "lec.h"
31#include "mpc.h"
32#include "resources.h"
33
34/*
35 * mpc.c: Implementation of MPOA client kernel part
36 */
37
38#if 0
39#define dprintk printk /* debug */
40#else
41#define dprintk(format,args...)
42#endif
43
44#if 0
45#define ddprintk printk /* more debug */
46#else
47#define ddprintk(format,args...)
48#endif
49
50
51
52#define MPOA_TAG_LEN 4
53
54/* mpc_daemon -> kernel */
55static void MPOA_trigger_rcvd (struct k_message *msg, struct mpoa_client *mpc);
56static void MPOA_res_reply_rcvd(struct k_message *msg, struct mpoa_client *mpc);
57static void ingress_purge_rcvd(struct k_message *msg, struct mpoa_client *mpc);
58static void egress_purge_rcvd(struct k_message *msg, struct mpoa_client *mpc);
59static void mps_death(struct k_message *msg, struct mpoa_client *mpc);
60static void clean_up(struct k_message *msg, struct mpoa_client *mpc, int action);
61static void MPOA_cache_impos_rcvd(struct k_message *msg, struct mpoa_client *mpc);
62static void set_mpc_ctrl_addr_rcvd(struct k_message *mesg, struct mpoa_client *mpc);
63static void set_mps_mac_addr_rcvd(struct k_message *mesg, struct mpoa_client *mpc);
64
65static uint8_t *copy_macs(struct mpoa_client *mpc, uint8_t *router_mac,
66 uint8_t *tlvs, uint8_t mps_macs, uint8_t device_type);
67static void purge_egress_shortcut(struct atm_vcc *vcc, eg_cache_entry *entry);
68
69static void send_set_mps_ctrl_addr(char *addr, struct mpoa_client *mpc);
70static void mpoad_close(struct atm_vcc *vcc);
71static int msg_from_mpoad(struct atm_vcc *vcc, struct sk_buff *skb);
72
73static void mpc_push(struct atm_vcc *vcc, struct sk_buff *skb);
74static int mpc_send_packet(struct sk_buff *skb, struct net_device *dev);
75static int mpoa_event_listener(struct notifier_block *mpoa_notifier, unsigned long event, void *dev);
76static void mpc_timer_refresh(void);
77static void mpc_cache_check( unsigned long checking_time );
78
79static struct llc_snap_hdr llc_snap_mpoa_ctrl = {
80 0xaa, 0xaa, 0x03,
81 {0x00, 0x00, 0x5e},
82 {0x00, 0x03} /* For MPOA control PDUs */
83};
84static struct llc_snap_hdr llc_snap_mpoa_data = {
85 0xaa, 0xaa, 0x03,
86 {0x00, 0x00, 0x00},
87 {0x08, 0x00} /* This is for IP PDUs only */
88};
89static struct llc_snap_hdr llc_snap_mpoa_data_tagged = {
90 0xaa, 0xaa, 0x03,
91 {0x00, 0x00, 0x00},
92 {0x88, 0x4c} /* This is for tagged data PDUs */
93};
94
95static struct notifier_block mpoa_notifier = {
96 mpoa_event_listener,
97 NULL,
98 0
99};
100
101#ifdef CONFIG_PROC_FS
102extern int mpc_proc_init(void);
103extern void mpc_proc_clean(void);
104#endif
105
106struct mpoa_client *mpcs = NULL; /* FIXME */
107static struct atm_mpoa_qos *qos_head = NULL;
108static struct timer_list mpc_timer = TIMER_INITIALIZER(NULL, 0, 0);
109
110
111static struct mpoa_client *find_mpc_by_itfnum(int itf)
112{
113 struct mpoa_client *mpc;
114
115 mpc = mpcs; /* our global linked list */
116 while (mpc != NULL) {
117 if (mpc->dev_num == itf)
118 return mpc;
119 mpc = mpc->next;
120 }
121
122 return NULL; /* not found */
123}
124
125static struct mpoa_client *find_mpc_by_vcc(struct atm_vcc *vcc)
126{
127 struct mpoa_client *mpc;
128
129 mpc = mpcs; /* our global linked list */
130 while (mpc != NULL) {
131 if (mpc->mpoad_vcc == vcc)
132 return mpc;
133 mpc = mpc->next;
134 }
135
136 return NULL; /* not found */
137}
138
139static struct mpoa_client *find_mpc_by_lec(struct net_device *dev)
140{
141 struct mpoa_client *mpc;
142
143 mpc = mpcs; /* our global linked list */
144 while (mpc != NULL) {
145 if (mpc->dev == dev)
146 return mpc;
147 mpc = mpc->next;
148 }
149
150 return NULL; /* not found */
151}
152
153/*
154 * Functions for managing QoS list
155 */
156
157/*
158 * Overwrites the old entry or makes a new one.
159 */
160struct atm_mpoa_qos *atm_mpoa_add_qos(uint32_t dst_ip, struct atm_qos *qos)
161{
162 struct atm_mpoa_qos *entry;
163
164 entry = atm_mpoa_search_qos(dst_ip);
165 if (entry != NULL) {
166 entry->qos = *qos;
167 return entry;
168 }
169
170 entry = kmalloc(sizeof(struct atm_mpoa_qos), GFP_KERNEL);
171 if (entry == NULL) {
172 printk("mpoa: atm_mpoa_add_qos: out of memory\n");
173 return entry;
174 }
175
176 entry->ipaddr = dst_ip;
177 entry->qos = *qos;
178
179 entry->next = qos_head;
180 qos_head = entry;
181
182 return entry;
183}
184
185struct atm_mpoa_qos *atm_mpoa_search_qos(uint32_t dst_ip)
186{
187 struct atm_mpoa_qos *qos;
188
189 qos = qos_head;
190 while( qos != NULL ){
191 if(qos->ipaddr == dst_ip) {
192 break;
193 }
194 qos = qos->next;
195 }
196
197 return qos;
198}
199
200/*
201 * Returns 0 for failure
202 */
203int atm_mpoa_delete_qos(struct atm_mpoa_qos *entry)
204{
205
206 struct atm_mpoa_qos *curr;
207
208 if (entry == NULL) return 0;
209 if (entry == qos_head) {
210 qos_head = qos_head->next;
211 kfree(entry);
212 return 1;
213 }
214
215 curr = qos_head;
216 while (curr != NULL) {
217 if (curr->next == entry) {
218 curr->next = entry->next;
219 kfree(entry);
220 return 1;
221 }
222 curr = curr->next;
223 }
224
225 return 0;
226}
227
228/* this is buggered - we need locking for qos_head */
229void atm_mpoa_disp_qos(struct seq_file *m)
230{
231 unsigned char *ip;
232 char ipaddr[16];
233 struct atm_mpoa_qos *qos;
234
235 qos = qos_head;
236 seq_printf(m, "QoS entries for shortcuts:\n");
237 seq_printf(m, "IP address\n TX:max_pcr pcr min_pcr max_cdv max_sdu\n RX:max_pcr pcr min_pcr max_cdv max_sdu\n");
238
239 ipaddr[sizeof(ipaddr)-1] = '\0';
240 while (qos != NULL) {
241 ip = (unsigned char *)&qos->ipaddr;
242 sprintf(ipaddr, "%u.%u.%u.%u", NIPQUAD(ip));
243 seq_printf(m, "%u.%u.%u.%u\n %-7d %-7d %-7d %-7d %-7d\n %-7d %-7d %-7d %-7d %-7d\n",
244 NIPQUAD(ipaddr),
245 qos->qos.txtp.max_pcr, qos->qos.txtp.pcr, qos->qos.txtp.min_pcr, qos->qos.txtp.max_cdv, qos->qos.txtp.max_sdu,
246 qos->qos.rxtp.max_pcr, qos->qos.rxtp.pcr, qos->qos.rxtp.min_pcr, qos->qos.rxtp.max_cdv, qos->qos.rxtp.max_sdu);
247 qos = qos->next;
248 }
249}
250
251static struct net_device *find_lec_by_itfnum(int itf)
252{
253 struct net_device *dev;
254 char name[IFNAMSIZ];
255
256 sprintf(name, "lec%d", itf);
257 dev = dev_get_by_name(name);
258
259 return dev;
260}
261
262static struct mpoa_client *alloc_mpc(void)
263{
264 struct mpoa_client *mpc;
265
266 mpc = kmalloc(sizeof (struct mpoa_client), GFP_KERNEL);
267 if (mpc == NULL)
268 return NULL;
269 memset(mpc, 0, sizeof(struct mpoa_client));
270 rwlock_init(&mpc->ingress_lock);
271 rwlock_init(&mpc->egress_lock);
272 mpc->next = mpcs;
273 atm_mpoa_init_cache(mpc);
274
275 mpc->parameters.mpc_p1 = MPC_P1;
276 mpc->parameters.mpc_p2 = MPC_P2;
277 memset(mpc->parameters.mpc_p3,0,sizeof(mpc->parameters.mpc_p3));
278 mpc->parameters.mpc_p4 = MPC_P4;
279 mpc->parameters.mpc_p5 = MPC_P5;
280 mpc->parameters.mpc_p6 = MPC_P6;
281
282 mpcs = mpc;
283
284 return mpc;
285}
286
287/*
288 *
289 * start_mpc() puts the MPC on line. All the packets destined
290 * to the lec underneath us are now being monitored and
291 * shortcuts will be established.
292 *
293 */
294static void start_mpc(struct mpoa_client *mpc, struct net_device *dev)
295{
296
297 dprintk("mpoa: (%s) start_mpc:\n", mpc->dev->name);
298 if (dev->hard_start_xmit == NULL) {
299 printk("mpoa: (%s) start_mpc: dev->hard_start_xmit == NULL, not starting\n",
300 dev->name);
301 return;
302 }
303 mpc->old_hard_start_xmit = dev->hard_start_xmit;
304 dev->hard_start_xmit = mpc_send_packet;
305
306 return;
307}
308
309static void stop_mpc(struct mpoa_client *mpc)
310{
311
312 dprintk("mpoa: (%s) stop_mpc:", mpc->dev->name);
313
314 /* Lets not nullify lec device's dev->hard_start_xmit */
315 if (mpc->dev->hard_start_xmit != mpc_send_packet) {
316 dprintk(" mpc already stopped, not fatal\n");
317 return;
318 }
319 dprintk("\n");
320 mpc->dev->hard_start_xmit = mpc->old_hard_start_xmit;
321 mpc->old_hard_start_xmit = NULL;
322 /* close_shortcuts(mpc); ??? FIXME */
323
324 return;
325}
326
327static const char *mpoa_device_type_string(char type) __attribute__ ((unused));
328
329static const char *mpoa_device_type_string(char type)
330{
331 switch(type) {
332 case NON_MPOA:
333 return "non-MPOA device";
334 break;
335 case MPS:
336 return "MPS";
337 break;
338 case MPC:
339 return "MPC";
340 break;
341 case MPS_AND_MPC:
342 return "both MPS and MPC";
343 break;
344 default:
345 return "unspecified (non-MPOA) device";
346 break;
347 }
348
349 return ""; /* not reached */
350}
351
352/*
353 * lec device calls this via its dev->priv->lane2_ops->associate_indicator()
354 * when it sees a TLV in LE_ARP packet.
355 * We fill in the pointer above when we see a LANE2 lec initializing
356 * See LANE2 spec 3.1.5
357 *
358 * Quite a big and ugly function but when you look at it
359 * all it does is to try to locate and parse MPOA Device
360 * Type TLV.
361 * We give our lec a pointer to this function and when the
362 * lec sees a TLV it uses the pointer to call this function.
363 *
364 */
365static void lane2_assoc_ind(struct net_device *dev, uint8_t *mac_addr,
366 uint8_t *tlvs, uint32_t sizeoftlvs)
367{
368 uint32_t type;
369 uint8_t length, mpoa_device_type, number_of_mps_macs;
370 uint8_t *end_of_tlvs;
371 struct mpoa_client *mpc;
372
373 mpoa_device_type = number_of_mps_macs = 0; /* silence gcc */
374 dprintk("mpoa: (%s) lane2_assoc_ind: received TLV(s), ", dev->name);
375 dprintk("total length of all TLVs %d\n", sizeoftlvs);
376 mpc = find_mpc_by_lec(dev); /* Sampo-Fix: moved here from below */
377 if (mpc == NULL) {
378 printk("mpoa: (%s) lane2_assoc_ind: no mpc\n", dev->name);
379 return;
380 }
381 end_of_tlvs = tlvs + sizeoftlvs;
382 while (end_of_tlvs - tlvs >= 5) {
383 type = (tlvs[0] << 24) | (tlvs[1] << 16) | (tlvs[2] << 8) | tlvs[3];
384 length = tlvs[4];
385 tlvs += 5;
386 dprintk(" type 0x%x length %02x\n", type, length);
387 if (tlvs + length > end_of_tlvs) {
388 printk("TLV value extends past its buffer, aborting parse\n");
389 return;
390 }
391
392 if (type == 0) {
393 printk("mpoa: (%s) lane2_assoc_ind: TLV type was 0, returning\n", dev->name);
394 return;
395 }
396
397 if (type != TLV_MPOA_DEVICE_TYPE) {
398 tlvs += length;
399 continue; /* skip other TLVs */
400 }
401 mpoa_device_type = *tlvs++;
402 number_of_mps_macs = *tlvs++;
403 dprintk("mpoa: (%s) MPOA device type '%s', ", dev->name, mpoa_device_type_string(mpoa_device_type));
404 if (mpoa_device_type == MPS_AND_MPC &&
405 length < (42 + number_of_mps_macs*ETH_ALEN)) { /* :) */
406 printk("\nmpoa: (%s) lane2_assoc_ind: short MPOA Device Type TLV\n",
407 dev->name);
408 continue;
409 }
410 if ((mpoa_device_type == MPS || mpoa_device_type == MPC)
411 && length < 22 + number_of_mps_macs*ETH_ALEN) {
412 printk("\nmpoa: (%s) lane2_assoc_ind: short MPOA Device Type TLV\n",
413 dev->name);
414 continue;
415 }
416 if (mpoa_device_type != MPS && mpoa_device_type != MPS_AND_MPC) {
417 dprintk("ignoring non-MPS device\n");
418 if (mpoa_device_type == MPC) tlvs += 20;
419 continue; /* we are only interested in MPSs */
420 }
421 if (number_of_mps_macs == 0 && mpoa_device_type == MPS_AND_MPC) {
422 printk("\nmpoa: (%s) lane2_assoc_ind: MPS_AND_MPC has zero MACs\n", dev->name);
423 continue; /* someone should read the spec */
424 }
425 dprintk("this MPS has %d MAC addresses\n", number_of_mps_macs);
426
427 /* ok, now we can go and tell our daemon the control address of MPS */
428 send_set_mps_ctrl_addr(tlvs, mpc);
429
430 tlvs = copy_macs(mpc, mac_addr, tlvs, number_of_mps_macs, mpoa_device_type);
431 if (tlvs == NULL) return;
432 }
433 if (end_of_tlvs - tlvs != 0)
434 printk("mpoa: (%s) lane2_assoc_ind: ignoring %Zd bytes of trailing TLV carbage\n",
435 dev->name, end_of_tlvs - tlvs);
436 return;
437}
438
439/*
440 * Store at least advertizing router's MAC address
441 * plus the possible MAC address(es) to mpc->mps_macs.
442 * For a freshly allocated MPOA client mpc->mps_macs == 0.
443 */
444static uint8_t *copy_macs(struct mpoa_client *mpc, uint8_t *router_mac,
445 uint8_t *tlvs, uint8_t mps_macs, uint8_t device_type)
446{
447 int num_macs;
448 num_macs = (mps_macs > 1) ? mps_macs : 1;
449
450 if (mpc->number_of_mps_macs != num_macs) { /* need to reallocate? */
451 if (mpc->number_of_mps_macs != 0) kfree(mpc->mps_macs);
452 mpc->number_of_mps_macs = 0;
453 mpc->mps_macs = kmalloc(num_macs*ETH_ALEN, GFP_KERNEL);
454 if (mpc->mps_macs == NULL) {
455 printk("mpoa: (%s) copy_macs: out of mem\n", mpc->dev->name);
456 return NULL;
457 }
458 }
459 memcpy(mpc->mps_macs, router_mac, ETH_ALEN);
460 tlvs += 20; if (device_type == MPS_AND_MPC) tlvs += 20;
461 if (mps_macs > 0)
462 memcpy(mpc->mps_macs, tlvs, mps_macs*ETH_ALEN);
463 tlvs += mps_macs*ETH_ALEN;
464 mpc->number_of_mps_macs = num_macs;
465
466 return tlvs;
467}
468
469static int send_via_shortcut(struct sk_buff *skb, struct mpoa_client *mpc)
470{
471 in_cache_entry *entry;
472 struct iphdr *iph;
473 char *buff;
474 uint32_t ipaddr = 0;
475
476 static struct {
477 struct llc_snap_hdr hdr;
478 uint32_t tag;
479 } tagged_llc_snap_hdr = {
480 {0xaa, 0xaa, 0x03, {0x00, 0x00, 0x00}, {0x88, 0x4c}},
481 0
482 };
483
484 buff = skb->data + mpc->dev->hard_header_len;
485 iph = (struct iphdr *)buff;
486 ipaddr = iph->daddr;
487
488 ddprintk("mpoa: (%s) send_via_shortcut: ipaddr 0x%x\n", mpc->dev->name, ipaddr);
489
490 entry = mpc->in_ops->get(ipaddr, mpc);
491 if (entry == NULL) {
492 entry = mpc->in_ops->add_entry(ipaddr, mpc);
493 if (entry != NULL) mpc->in_ops->put(entry);
494 return 1;
495 }
496 if (mpc->in_ops->cache_hit(entry, mpc) != OPEN){ /* threshold not exceeded or VCC not ready */
497 ddprintk("mpoa: (%s) send_via_shortcut: cache_hit: returns != OPEN\n", mpc->dev->name);
498 mpc->in_ops->put(entry);
499 return 1;
500 }
501
502 ddprintk("mpoa: (%s) send_via_shortcut: using shortcut\n", mpc->dev->name);
503 /* MPOA spec A.1.4, MPOA client must decrement IP ttl at least by one */
504 if (iph->ttl <= 1) {
505 ddprintk("mpoa: (%s) send_via_shortcut: IP ttl = %u, using LANE\n", mpc->dev->name, iph->ttl);
506 mpc->in_ops->put(entry);
507 return 1;
508 }
509 iph->ttl--;
510 iph->check = 0;
511 iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
512
513 if (entry->ctrl_info.tag != 0) {
514 ddprintk("mpoa: (%s) send_via_shortcut: adding tag 0x%x\n", mpc->dev->name, entry->ctrl_info.tag);
515 tagged_llc_snap_hdr.tag = entry->ctrl_info.tag;
516 skb_pull(skb, ETH_HLEN); /* get rid of Eth header */
517 skb_push(skb, sizeof(tagged_llc_snap_hdr)); /* add LLC/SNAP header */
518 memcpy(skb->data, &tagged_llc_snap_hdr, sizeof(tagged_llc_snap_hdr));
519 } else {
520 skb_pull(skb, ETH_HLEN); /* get rid of Eth header */
521 skb_push(skb, sizeof(struct llc_snap_hdr)); /* add LLC/SNAP header + tag */
522 memcpy(skb->data, &llc_snap_mpoa_data, sizeof(struct llc_snap_hdr));
523 }
524
525 atomic_add(skb->truesize, &sk_atm(entry->shortcut)->sk_wmem_alloc);
526 ATM_SKB(skb)->atm_options = entry->shortcut->atm_options;
527 entry->shortcut->send(entry->shortcut, skb);
528 entry->packets_fwded++;
529 mpc->in_ops->put(entry);
530
531 return 0;
532}
533
534/*
535 * Probably needs some error checks and locking, not sure...
536 */
537static int mpc_send_packet(struct sk_buff *skb, struct net_device *dev)
538{
539 int retval;
540 struct mpoa_client *mpc;
541 struct ethhdr *eth;
542 int i = 0;
543
544 mpc = find_mpc_by_lec(dev); /* this should NEVER fail */
545 if(mpc == NULL) {
546 printk("mpoa: (%s) mpc_send_packet: no MPC found\n", dev->name);
547 goto non_ip;
548 }
549
550 eth = (struct ethhdr *)skb->data;
551 if (eth->h_proto != htons(ETH_P_IP))
552 goto non_ip; /* Multi-Protocol Over ATM :-) */
553
554 while (i < mpc->number_of_mps_macs) {
555 if (memcmp(eth->h_dest, (mpc->mps_macs + i*ETH_ALEN), ETH_ALEN) == 0)
556 if ( send_via_shortcut(skb, mpc) == 0 ) /* try shortcut */
557 return 0; /* success! */
558 i++;
559 }
560
561 non_ip:
562 retval = mpc->old_hard_start_xmit(skb,dev);
563
564 return retval;
565}
566
567static int atm_mpoa_vcc_attach(struct atm_vcc *vcc, void __user *arg)
568{
569 int bytes_left;
570 struct mpoa_client *mpc;
571 struct atmmpc_ioc ioc_data;
572 in_cache_entry *in_entry;
573 uint32_t ipaddr;
574 unsigned char *ip;
575
576 bytes_left = copy_from_user(&ioc_data, arg, sizeof(struct atmmpc_ioc));
577 if (bytes_left != 0) {
578 printk("mpoa: mpc_vcc_attach: Short read (missed %d bytes) from userland\n", bytes_left);
579 return -EFAULT;
580 }
581 ipaddr = ioc_data.ipaddr;
582 if (ioc_data.dev_num < 0 || ioc_data.dev_num >= MAX_LEC_ITF)
583 return -EINVAL;
584
585 mpc = find_mpc_by_itfnum(ioc_data.dev_num);
586 if (mpc == NULL)
587 return -EINVAL;
588
589 if (ioc_data.type == MPC_SOCKET_INGRESS) {
590 in_entry = mpc->in_ops->get(ipaddr, mpc);
591 if (in_entry == NULL || in_entry->entry_state < INGRESS_RESOLVED) {
592 printk("mpoa: (%s) mpc_vcc_attach: did not find RESOLVED entry from ingress cache\n",
593 mpc->dev->name);
594 if (in_entry != NULL) mpc->in_ops->put(in_entry);
595 return -EINVAL;
596 }
597 ip = (unsigned char*)&in_entry->ctrl_info.in_dst_ip;
598 printk("mpoa: (%s) mpc_vcc_attach: attaching ingress SVC, entry = %u.%u.%u.%u\n",
599 mpc->dev->name, ip[0], ip[1], ip[2], ip[3]);
600 in_entry->shortcut = vcc;
601 mpc->in_ops->put(in_entry);
602 } else {
603 printk("mpoa: (%s) mpc_vcc_attach: attaching egress SVC\n", mpc->dev->name);
604 }
605
606 vcc->proto_data = mpc->dev;
607 vcc->push = mpc_push;
608
609 return 0;
610}
611
612/*
613 *
614 */
615static void mpc_vcc_close(struct atm_vcc *vcc, struct net_device *dev)
616{
617 struct mpoa_client *mpc;
618 in_cache_entry *in_entry;
619 eg_cache_entry *eg_entry;
620
621 mpc = find_mpc_by_lec(dev);
622 if (mpc == NULL) {
623 printk("mpoa: (%s) mpc_vcc_close: close for unknown MPC\n", dev->name);
624 return;
625 }
626
627 dprintk("mpoa: (%s) mpc_vcc_close:\n", dev->name);
628 in_entry = mpc->in_ops->get_by_vcc(vcc, mpc);
629 if (in_entry) {
630 unsigned char *ip __attribute__ ((unused)) =
631 (unsigned char *)&in_entry->ctrl_info.in_dst_ip;
632 dprintk("mpoa: (%s) mpc_vcc_close: ingress SVC closed ip = %u.%u.%u.%u\n",
633 mpc->dev->name, ip[0], ip[1], ip[2], ip[3]);
634 in_entry->shortcut = NULL;
635 mpc->in_ops->put(in_entry);
636 }
637 eg_entry = mpc->eg_ops->get_by_vcc(vcc, mpc);
638 if (eg_entry) {
639 dprintk("mpoa: (%s) mpc_vcc_close: egress SVC closed\n", mpc->dev->name);
640 eg_entry->shortcut = NULL;
641 mpc->eg_ops->put(eg_entry);
642 }
643
644 if (in_entry == NULL && eg_entry == NULL)
645 dprintk("mpoa: (%s) mpc_vcc_close: unused vcc closed\n", dev->name);
646
647 return;
648}
649
650static void mpc_push(struct atm_vcc *vcc, struct sk_buff *skb)
651{
652 struct net_device *dev = (struct net_device *)vcc->proto_data;
653 struct sk_buff *new_skb;
654 eg_cache_entry *eg;
655 struct mpoa_client *mpc;
656 uint32_t tag;
657 char *tmp;
658
659 ddprintk("mpoa: (%s) mpc_push:\n", dev->name);
660 if (skb == NULL) {
661 dprintk("mpoa: (%s) mpc_push: null skb, closing VCC\n", dev->name);
662 mpc_vcc_close(vcc, dev);
663 return;
664 }
665
666 skb->dev = dev;
667 if (memcmp(skb->data, &llc_snap_mpoa_ctrl, sizeof(struct llc_snap_hdr)) == 0) {
668 struct sock *sk = sk_atm(vcc);
669
670 dprintk("mpoa: (%s) mpc_push: control packet arrived\n", dev->name);
671 /* Pass control packets to daemon */
672 skb_queue_tail(&sk->sk_receive_queue, skb);
673 sk->sk_data_ready(sk, skb->len);
674 return;
675 }
676
677 /* data coming over the shortcut */
678 atm_return(vcc, skb->truesize);
679
680 mpc = find_mpc_by_lec(dev);
681 if (mpc == NULL) {
682 printk("mpoa: (%s) mpc_push: unknown MPC\n", dev->name);
683 return;
684 }
685
686 if (memcmp(skb->data, &llc_snap_mpoa_data_tagged, sizeof(struct llc_snap_hdr)) == 0) { /* MPOA tagged data */
687 ddprintk("mpoa: (%s) mpc_push: tagged data packet arrived\n", dev->name);
688
689 } else if (memcmp(skb->data, &llc_snap_mpoa_data, sizeof(struct llc_snap_hdr)) == 0) { /* MPOA data */
690 printk("mpoa: (%s) mpc_push: non-tagged data packet arrived\n", dev->name);
691 printk(" mpc_push: non-tagged data unsupported, purging\n");
692 dev_kfree_skb_any(skb);
693 return;
694 } else {
695 printk("mpoa: (%s) mpc_push: garbage arrived, purging\n", dev->name);
696 dev_kfree_skb_any(skb);
697 return;
698 }
699
700 tmp = skb->data + sizeof(struct llc_snap_hdr);
701 tag = *(uint32_t *)tmp;
702
703 eg = mpc->eg_ops->get_by_tag(tag, mpc);
704 if (eg == NULL) {
705 printk("mpoa: (%s) mpc_push: Didn't find egress cache entry, tag = %u\n",
706 dev->name,tag);
707 purge_egress_shortcut(vcc, NULL);
708 dev_kfree_skb_any(skb);
709 return;
710 }
711
712 /*
713 * See if ingress MPC is using shortcut we opened as a return channel.
714 * This means we have a bi-directional vcc opened by us.
715 */
716 if (eg->shortcut == NULL) {
717 eg->shortcut = vcc;
718 printk("mpoa: (%s) mpc_push: egress SVC in use\n", dev->name);
719 }
720
721 skb_pull(skb, sizeof(struct llc_snap_hdr) + sizeof(tag)); /* get rid of LLC/SNAP header */
722 new_skb = skb_realloc_headroom(skb, eg->ctrl_info.DH_length); /* LLC/SNAP is shorter than MAC header :( */
723 dev_kfree_skb_any(skb);
724 if (new_skb == NULL){
725 mpc->eg_ops->put(eg);
726 return;
727 }
728 skb_push(new_skb, eg->ctrl_info.DH_length); /* add MAC header */
729 memcpy(new_skb->data, eg->ctrl_info.DLL_header, eg->ctrl_info.DH_length);
730 new_skb->protocol = eth_type_trans(new_skb, dev);
731 new_skb->nh.raw = new_skb->data;
732
733 eg->latest_ip_addr = new_skb->nh.iph->saddr;
734 eg->packets_rcvd++;
735 mpc->eg_ops->put(eg);
736
737 memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data));
738 netif_rx(new_skb);
739
740 return;
741}
742
743static struct atmdev_ops mpc_ops = { /* only send is required */
744 .close = mpoad_close,
745 .send = msg_from_mpoad
746};
747
748static struct atm_dev mpc_dev = {
749 .ops = &mpc_ops,
750 .type = "mpc",
751 .number = 42,
752 .lock = SPIN_LOCK_UNLOCKED
753 /* members not explicitly initialised will be 0 */
754};
755
756static int atm_mpoa_mpoad_attach (struct atm_vcc *vcc, int arg)
757{
758 struct mpoa_client *mpc;
759 struct lec_priv *priv;
760 int err;
761
762 if (mpcs == NULL) {
763 init_timer(&mpc_timer);
764 mpc_timer_refresh();
765
766 /* This lets us now how our LECs are doing */
767 err = register_netdevice_notifier(&mpoa_notifier);
768 if (err < 0) {
769 del_timer(&mpc_timer);
770 return err;
771 }
772 }
773
774 mpc = find_mpc_by_itfnum(arg);
775 if (mpc == NULL) {
776 dprintk("mpoa: mpoad_attach: allocating new mpc for itf %d\n", arg);
777 mpc = alloc_mpc();
778 if (mpc == NULL)
779 return -ENOMEM;
780 mpc->dev_num = arg;
781 mpc->dev = find_lec_by_itfnum(arg); /* NULL if there was no lec */
782 }
783 if (mpc->mpoad_vcc) {
784 printk("mpoa: mpoad_attach: mpoad is already present for itf %d\n", arg);
785 return -EADDRINUSE;
786 }
787
788 if (mpc->dev) { /* check if the lec is LANE2 capable */
789 priv = (struct lec_priv *)mpc->dev->priv;
790 if (priv->lane_version < 2) {
791 dev_put(mpc->dev);
792 mpc->dev = NULL;
793 } else
794 priv->lane2_ops->associate_indicator = lane2_assoc_ind;
795 }
796
797 mpc->mpoad_vcc = vcc;
798 vcc->dev = &mpc_dev;
799 vcc_insert_socket(sk_atm(vcc));
800 set_bit(ATM_VF_META,&vcc->flags);
801 set_bit(ATM_VF_READY,&vcc->flags);
802
803 if (mpc->dev) {
804 char empty[ATM_ESA_LEN];
805 memset(empty, 0, ATM_ESA_LEN);
806
807 start_mpc(mpc, mpc->dev);
808 /* set address if mpcd e.g. gets killed and restarted.
809 * If we do not do it now we have to wait for the next LE_ARP
810 */
811 if ( memcmp(mpc->mps_ctrl_addr, empty, ATM_ESA_LEN) != 0 )
812 send_set_mps_ctrl_addr(mpc->mps_ctrl_addr, mpc);
813 }
814
815 __module_get(THIS_MODULE);
816 return arg;
817}
818
819static void send_set_mps_ctrl_addr(char *addr, struct mpoa_client *mpc)
820{
821 struct k_message mesg;
822
823 memcpy (mpc->mps_ctrl_addr, addr, ATM_ESA_LEN);
824
825 mesg.type = SET_MPS_CTRL_ADDR;
826 memcpy(mesg.MPS_ctrl, addr, ATM_ESA_LEN);
827 msg_to_mpoad(&mesg, mpc);
828
829 return;
830}
831
832static void mpoad_close(struct atm_vcc *vcc)
833{
834 struct mpoa_client *mpc;
835 struct sk_buff *skb;
836
837 mpc = find_mpc_by_vcc(vcc);
838 if (mpc == NULL) {
839 printk("mpoa: mpoad_close: did not find MPC\n");
840 return;
841 }
842 if (!mpc->mpoad_vcc) {
843 printk("mpoa: mpoad_close: close for non-present mpoad\n");
844 return;
845 }
846
847 mpc->mpoad_vcc = NULL;
848 if (mpc->dev) {
849 struct lec_priv *priv = (struct lec_priv *)mpc->dev->priv;
850 priv->lane2_ops->associate_indicator = NULL;
851 stop_mpc(mpc);
852 dev_put(mpc->dev);
853 }
854
855 mpc->in_ops->destroy_cache(mpc);
856 mpc->eg_ops->destroy_cache(mpc);
857
858 while ((skb = skb_dequeue(&sk_atm(vcc)->sk_receive_queue))) {
859 atm_return(vcc, skb->truesize);
860 kfree_skb(skb);
861 }
862
863 printk("mpoa: (%s) going down\n",
864 (mpc->dev) ? mpc->dev->name : "<unknown>");
865 module_put(THIS_MODULE);
866
867 return;
868}
869
870/*
871 *
872 */
873static int msg_from_mpoad(struct atm_vcc *vcc, struct sk_buff *skb)
874{
875
876 struct mpoa_client *mpc = find_mpc_by_vcc(vcc);
877 struct k_message *mesg = (struct k_message*)skb->data;
878 atomic_sub(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
879
880 if (mpc == NULL) {
881 printk("mpoa: msg_from_mpoad: no mpc found\n");
882 return 0;
883 }
884 dprintk("mpoa: (%s) msg_from_mpoad:", (mpc->dev) ? mpc->dev->name : "<unknown>");
885 switch(mesg->type) {
886 case MPOA_RES_REPLY_RCVD:
887 dprintk(" mpoa_res_reply_rcvd\n");
888 MPOA_res_reply_rcvd(mesg, mpc);
889 break;
890 case MPOA_TRIGGER_RCVD:
891 dprintk(" mpoa_trigger_rcvd\n");
892 MPOA_trigger_rcvd(mesg, mpc);
893 break;
894 case INGRESS_PURGE_RCVD:
895 dprintk(" nhrp_purge_rcvd\n");
896 ingress_purge_rcvd(mesg, mpc);
897 break;
898 case EGRESS_PURGE_RCVD:
899 dprintk(" egress_purge_reply_rcvd\n");
900 egress_purge_rcvd(mesg, mpc);
901 break;
902 case MPS_DEATH:
903 dprintk(" mps_death\n");
904 mps_death(mesg, mpc);
905 break;
906 case CACHE_IMPOS_RCVD:
907 dprintk(" cache_impos_rcvd\n");
908 MPOA_cache_impos_rcvd(mesg, mpc);
909 break;
910 case SET_MPC_CTRL_ADDR:
911 dprintk(" set_mpc_ctrl_addr\n");
912 set_mpc_ctrl_addr_rcvd(mesg, mpc);
913 break;
914 case SET_MPS_MAC_ADDR:
915 dprintk(" set_mps_mac_addr\n");
916 set_mps_mac_addr_rcvd(mesg, mpc);
917 break;
918 case CLEAN_UP_AND_EXIT:
919 dprintk(" clean_up_and_exit\n");
920 clean_up(mesg, mpc, DIE);
921 break;
922 case RELOAD:
923 dprintk(" reload\n");
924 clean_up(mesg, mpc, RELOAD);
925 break;
926 case SET_MPC_PARAMS:
927 dprintk(" set_mpc_params\n");
928 mpc->parameters = mesg->content.params;
929 break;
930 default:
931 dprintk(" unknown message %d\n", mesg->type);
932 break;
933 }
934 kfree_skb(skb);
935
936 return 0;
937}
938
939/* Remember that this function may not do things that sleep */
940int msg_to_mpoad(struct k_message *mesg, struct mpoa_client *mpc)
941{
942 struct sk_buff *skb;
943 struct sock *sk;
944
945 if (mpc == NULL || !mpc->mpoad_vcc) {
946 printk("mpoa: msg_to_mpoad: mesg %d to a non-existent mpoad\n", mesg->type);
947 return -ENXIO;
948 }
949
950 skb = alloc_skb(sizeof(struct k_message), GFP_ATOMIC);
951 if (skb == NULL)
952 return -ENOMEM;
953 skb_put(skb, sizeof(struct k_message));
954 memcpy(skb->data, mesg, sizeof(struct k_message));
955 atm_force_charge(mpc->mpoad_vcc, skb->truesize);
956
957 sk = sk_atm(mpc->mpoad_vcc);
958 skb_queue_tail(&sk->sk_receive_queue, skb);
959 sk->sk_data_ready(sk, skb->len);
960
961 return 0;
962}
963
964static int mpoa_event_listener(struct notifier_block *mpoa_notifier, unsigned long event, void *dev_ptr)
965{
966 struct net_device *dev;
967 struct mpoa_client *mpc;
968 struct lec_priv *priv;
969
970 dev = (struct net_device *)dev_ptr;
971 if (dev->name == NULL || strncmp(dev->name, "lec", 3))
972 return NOTIFY_DONE; /* we are only interested in lec:s */
973
974 switch (event) {
975 case NETDEV_REGISTER: /* a new lec device was allocated */
976 priv = (struct lec_priv *)dev->priv;
977 if (priv->lane_version < 2)
978 break;
979 priv->lane2_ops->associate_indicator = lane2_assoc_ind;
980 mpc = find_mpc_by_itfnum(priv->itfnum);
981 if (mpc == NULL) {
982 dprintk("mpoa: mpoa_event_listener: allocating new mpc for %s\n",
983 dev->name);
984 mpc = alloc_mpc();
985 if (mpc == NULL) {
986 printk("mpoa: mpoa_event_listener: no new mpc");
987 break;
988 }
989 }
990 mpc->dev_num = priv->itfnum;
991 mpc->dev = dev;
992 dev_hold(dev);
993 dprintk("mpoa: (%s) was initialized\n", dev->name);
994 break;
995 case NETDEV_UNREGISTER:
996 /* the lec device was deallocated */
997 mpc = find_mpc_by_lec(dev);
998 if (mpc == NULL)
999 break;
1000 dprintk("mpoa: device (%s) was deallocated\n", dev->name);
1001 stop_mpc(mpc);
1002 dev_put(mpc->dev);
1003 mpc->dev = NULL;
1004 break;
1005 case NETDEV_UP:
1006 /* the dev was ifconfig'ed up */
1007 mpc = find_mpc_by_lec(dev);
1008 if (mpc == NULL)
1009 break;
1010 if (mpc->mpoad_vcc != NULL) {
1011 start_mpc(mpc, dev);
1012 }
1013 break;
1014 case NETDEV_DOWN:
1015 /* the dev was ifconfig'ed down */
1016 /* this means that the flow of packets from the
1017 * upper layer stops
1018 */
1019 mpc = find_mpc_by_lec(dev);
1020 if (mpc == NULL)
1021 break;
1022 if (mpc->mpoad_vcc != NULL) {
1023 stop_mpc(mpc);
1024 }
1025 break;
1026 case NETDEV_REBOOT:
1027 case NETDEV_CHANGE:
1028 case NETDEV_CHANGEMTU:
1029 case NETDEV_CHANGEADDR:
1030 case NETDEV_GOING_DOWN:
1031 break;
1032 default:
1033 break;
1034 }
1035
1036 return NOTIFY_DONE;
1037}
1038
1039/*
1040 * Functions which are called after a message is received from mpcd.
1041 * Msg is reused on purpose.
1042 */
1043
1044
1045static void MPOA_trigger_rcvd(struct k_message *msg, struct mpoa_client *mpc)
1046{
1047 uint32_t dst_ip = msg->content.in_info.in_dst_ip;
1048 in_cache_entry *entry;
1049
1050 entry = mpc->in_ops->get(dst_ip, mpc);
1051 if(entry == NULL){
1052 entry = mpc->in_ops->add_entry(dst_ip, mpc);
1053 entry->entry_state = INGRESS_RESOLVING;
1054 msg->type = SND_MPOA_RES_RQST;
1055 msg->content.in_info = entry->ctrl_info;
1056 msg_to_mpoad(msg, mpc);
1057 do_gettimeofday(&(entry->reply_wait));
1058 mpc->in_ops->put(entry);
1059 return;
1060 }
1061
1062 if(entry->entry_state == INGRESS_INVALID){
1063 entry->entry_state = INGRESS_RESOLVING;
1064 msg->type = SND_MPOA_RES_RQST;
1065 msg->content.in_info = entry->ctrl_info;
1066 msg_to_mpoad(msg, mpc);
1067 do_gettimeofday(&(entry->reply_wait));
1068 mpc->in_ops->put(entry);
1069 return;
1070 }
1071
1072 printk("mpoa: (%s) MPOA_trigger_rcvd: entry already in resolving state\n",
1073 (mpc->dev) ? mpc->dev->name : "<unknown>");
1074 mpc->in_ops->put(entry);
1075 return;
1076}
1077
1078/*
1079 * Things get complicated because we have to check if there's an egress
1080 * shortcut with suitable traffic parameters we could use.
1081 */
1082static void check_qos_and_open_shortcut(struct k_message *msg, struct mpoa_client *client, in_cache_entry *entry)
1083{
1084 uint32_t dst_ip = msg->content.in_info.in_dst_ip;
1085 unsigned char *ip __attribute__ ((unused)) = (unsigned char *)&dst_ip;
1086 struct atm_mpoa_qos *qos = atm_mpoa_search_qos(dst_ip);
1087 eg_cache_entry *eg_entry = client->eg_ops->get_by_src_ip(dst_ip, client);
1088
1089 if(eg_entry && eg_entry->shortcut){
1090 if(eg_entry->shortcut->qos.txtp.traffic_class &
1091 msg->qos.txtp.traffic_class &
1092 (qos ? qos->qos.txtp.traffic_class : ATM_UBR | ATM_CBR)){
1093 if(eg_entry->shortcut->qos.txtp.traffic_class == ATM_UBR)
1094 entry->shortcut = eg_entry->shortcut;
1095 else if(eg_entry->shortcut->qos.txtp.max_pcr > 0)
1096 entry->shortcut = eg_entry->shortcut;
1097 }
1098 if(entry->shortcut){
1099 dprintk("mpoa: (%s) using egress SVC to reach %u.%u.%u.%u\n",client->dev->name, NIPQUAD(ip));
1100 client->eg_ops->put(eg_entry);
1101 return;
1102 }
1103 }
1104 if (eg_entry != NULL)
1105 client->eg_ops->put(eg_entry);
1106
1107 /* No luck in the egress cache we must open an ingress SVC */
1108 msg->type = OPEN_INGRESS_SVC;
1109 if (qos && (qos->qos.txtp.traffic_class == msg->qos.txtp.traffic_class))
1110 {
1111 msg->qos = qos->qos;
1112 printk("mpoa: (%s) trying to get a CBR shortcut\n",client->dev->name);
1113 }
1114 else memset(&msg->qos,0,sizeof(struct atm_qos));
1115 msg_to_mpoad(msg, client);
1116 return;
1117}
1118
1119static void MPOA_res_reply_rcvd(struct k_message *msg, struct mpoa_client *mpc)
1120{
1121 unsigned char *ip;
1122
1123 uint32_t dst_ip = msg->content.in_info.in_dst_ip;
1124 in_cache_entry *entry = mpc->in_ops->get(dst_ip, mpc);
1125 ip = (unsigned char *)&dst_ip;
1126 dprintk("mpoa: (%s) MPOA_res_reply_rcvd: ip %u.%u.%u.%u\n", mpc->dev->name, NIPQUAD(ip));
1127 ddprintk("mpoa: (%s) MPOA_res_reply_rcvd() entry = %p", mpc->dev->name, entry);
1128 if(entry == NULL){
1129 printk("\nmpoa: (%s) ARGH, received res. reply for an entry that doesn't exist.\n", mpc->dev->name);
1130 return;
1131 }
1132 ddprintk(" entry_state = %d ", entry->entry_state);
1133
1134 if (entry->entry_state == INGRESS_RESOLVED) {
1135 printk("\nmpoa: (%s) MPOA_res_reply_rcvd for RESOLVED entry!\n", mpc->dev->name);
1136 mpc->in_ops->put(entry);
1137 return;
1138 }
1139
1140 entry->ctrl_info = msg->content.in_info;
1141 do_gettimeofday(&(entry->tv));
1142 do_gettimeofday(&(entry->reply_wait)); /* Used in refreshing func from now on */
1143 entry->refresh_time = 0;
1144 ddprintk("entry->shortcut = %p\n", entry->shortcut);
1145
1146 if(entry->entry_state == INGRESS_RESOLVING && entry->shortcut != NULL){
1147 entry->entry_state = INGRESS_RESOLVED;
1148 mpc->in_ops->put(entry);
1149 return; /* Shortcut already open... */
1150 }
1151
1152 if (entry->shortcut != NULL) {
1153 printk("mpoa: (%s) MPOA_res_reply_rcvd: entry->shortcut != NULL, impossible!\n",
1154 mpc->dev->name);
1155 mpc->in_ops->put(entry);
1156 return;
1157 }
1158
1159 check_qos_and_open_shortcut(msg, mpc, entry);
1160 entry->entry_state = INGRESS_RESOLVED;
1161 mpc->in_ops->put(entry);
1162
1163 return;
1164
1165}
1166
1167static void ingress_purge_rcvd(struct k_message *msg, struct mpoa_client *mpc)
1168{
1169 uint32_t dst_ip = msg->content.in_info.in_dst_ip;
1170 uint32_t mask = msg->ip_mask;
1171 unsigned char *ip = (unsigned char *)&dst_ip;
1172 in_cache_entry *entry = mpc->in_ops->get_with_mask(dst_ip, mpc, mask);
1173
1174 if(entry == NULL){
1175 printk("mpoa: (%s) ingress_purge_rcvd: purge for a non-existing entry, ", mpc->dev->name);
1176 printk("ip = %u.%u.%u.%u\n", ip[0], ip[1], ip[2], ip[3]);
1177 return;
1178 }
1179
1180 do {
1181 dprintk("mpoa: (%s) ingress_purge_rcvd: removing an ingress entry, ip = %u.%u.%u.%u\n" ,
1182 mpc->dev->name, ip[0], ip[1], ip[2], ip[3]);
1183 write_lock_bh(&mpc->ingress_lock);
1184 mpc->in_ops->remove_entry(entry, mpc);
1185 write_unlock_bh(&mpc->ingress_lock);
1186 mpc->in_ops->put(entry);
1187 entry = mpc->in_ops->get_with_mask(dst_ip, mpc, mask);
1188 } while (entry != NULL);
1189
1190 return;
1191}
1192
1193static void egress_purge_rcvd(struct k_message *msg, struct mpoa_client *mpc)
1194{
1195 uint32_t cache_id = msg->content.eg_info.cache_id;
1196 eg_cache_entry *entry = mpc->eg_ops->get_by_cache_id(cache_id, mpc);
1197
1198 if (entry == NULL) {
1199 dprintk("mpoa: (%s) egress_purge_rcvd: purge for a non-existing entry\n", mpc->dev->name);
1200 return;
1201 }
1202
1203 write_lock_irq(&mpc->egress_lock);
1204 mpc->eg_ops->remove_entry(entry, mpc);
1205 write_unlock_irq(&mpc->egress_lock);
1206
1207 mpc->eg_ops->put(entry);
1208
1209 return;
1210}
1211
1212static void purge_egress_shortcut(struct atm_vcc *vcc, eg_cache_entry *entry)
1213{
1214 struct sock *sk;
1215 struct k_message *purge_msg;
1216 struct sk_buff *skb;
1217
1218 dprintk("mpoa: purge_egress_shortcut: entering\n");
1219 if (vcc == NULL) {
1220 printk("mpoa: purge_egress_shortcut: vcc == NULL\n");
1221 return;
1222 }
1223
1224 skb = alloc_skb(sizeof(struct k_message), GFP_ATOMIC);
1225 if (skb == NULL) {
1226 printk("mpoa: purge_egress_shortcut: out of memory\n");
1227 return;
1228 }
1229
1230 skb_put(skb, sizeof(struct k_message));
1231 memset(skb->data, 0, sizeof(struct k_message));
1232 purge_msg = (struct k_message *)skb->data;
1233 purge_msg->type = DATA_PLANE_PURGE;
1234 if (entry != NULL)
1235 purge_msg->content.eg_info = entry->ctrl_info;
1236
1237 atm_force_charge(vcc, skb->truesize);
1238
1239 sk = sk_atm(vcc);
1240 skb_queue_tail(&sk->sk_receive_queue, skb);
1241 sk->sk_data_ready(sk, skb->len);
1242 dprintk("mpoa: purge_egress_shortcut: exiting:\n");
1243
1244 return;
1245}
1246
1247/*
1248 * Our MPS died. Tell our daemon to send NHRP data plane purge to each
1249 * of the egress shortcuts we have.
1250 */
1251static void mps_death( struct k_message * msg, struct mpoa_client * mpc )
1252{
1253 eg_cache_entry *entry;
1254
1255 dprintk("mpoa: (%s) mps_death:\n", mpc->dev->name);
1256
1257 if(memcmp(msg->MPS_ctrl, mpc->mps_ctrl_addr, ATM_ESA_LEN)){
1258 printk("mpoa: (%s) mps_death: wrong MPS\n", mpc->dev->name);
1259 return;
1260 }
1261
1262 /* FIXME: This knows too much of the cache structure */
1263 read_lock_irq(&mpc->egress_lock);
1264 entry = mpc->eg_cache;
1265 while (entry != NULL) {
1266 purge_egress_shortcut(entry->shortcut, entry);
1267 entry = entry->next;
1268 }
1269 read_unlock_irq(&mpc->egress_lock);
1270
1271 mpc->in_ops->destroy_cache(mpc);
1272 mpc->eg_ops->destroy_cache(mpc);
1273
1274 return;
1275}
1276
1277static void MPOA_cache_impos_rcvd( struct k_message * msg, struct mpoa_client * mpc)
1278{
1279 uint16_t holding_time;
1280 eg_cache_entry *entry = mpc->eg_ops->get_by_cache_id(msg->content.eg_info.cache_id, mpc);
1281
1282 holding_time = msg->content.eg_info.holding_time;
1283 dprintk("mpoa: (%s) MPOA_cache_impos_rcvd: entry = %p, holding_time = %u\n",
1284 mpc->dev->name, entry, holding_time);
1285 if(entry == NULL && holding_time) {
1286 entry = mpc->eg_ops->add_entry(msg, mpc);
1287 mpc->eg_ops->put(entry);
1288 return;
1289 }
1290 if(holding_time){
1291 mpc->eg_ops->update(entry, holding_time);
1292 return;
1293 }
1294
1295 write_lock_irq(&mpc->egress_lock);
1296 mpc->eg_ops->remove_entry(entry, mpc);
1297 write_unlock_irq(&mpc->egress_lock);
1298
1299 mpc->eg_ops->put(entry);
1300
1301 return;
1302}
1303
1304static void set_mpc_ctrl_addr_rcvd(struct k_message *mesg, struct mpoa_client *mpc)
1305{
1306 struct lec_priv *priv;
1307 int i, retval ;
1308
1309 uint8_t tlv[4 + 1 + 1 + 1 + ATM_ESA_LEN];
1310
1311 tlv[0] = 00; tlv[1] = 0xa0; tlv[2] = 0x3e; tlv[3] = 0x2a; /* type */
1312 tlv[4] = 1 + 1 + ATM_ESA_LEN; /* length */
1313 tlv[5] = 0x02; /* MPOA client */
1314 tlv[6] = 0x00; /* number of MPS MAC addresses */
1315
1316 memcpy(&tlv[7], mesg->MPS_ctrl, ATM_ESA_LEN); /* MPC ctrl ATM addr */
1317 memcpy(mpc->our_ctrl_addr, mesg->MPS_ctrl, ATM_ESA_LEN);
1318
1319 dprintk("mpoa: (%s) setting MPC ctrl ATM address to ",
1320 (mpc->dev) ? mpc->dev->name : "<unknown>");
1321 for (i = 7; i < sizeof(tlv); i++)
1322 dprintk("%02x ", tlv[i]);
1323 dprintk("\n");
1324
1325 if (mpc->dev) {
1326 priv = (struct lec_priv *)mpc->dev->priv;
1327 retval = priv->lane2_ops->associate_req(mpc->dev, mpc->dev->dev_addr, tlv, sizeof(tlv));
1328 if (retval == 0)
1329 printk("mpoa: (%s) MPOA device type TLV association failed\n", mpc->dev->name);
1330 retval = priv->lane2_ops->resolve(mpc->dev, NULL, 1, NULL, NULL);
1331 if (retval < 0)
1332 printk("mpoa: (%s) targetless LE_ARP request failed\n", mpc->dev->name);
1333 }
1334
1335 return;
1336}
1337
1338static void set_mps_mac_addr_rcvd(struct k_message *msg, struct mpoa_client *client)
1339{
1340
1341 if(client->number_of_mps_macs)
1342 kfree(client->mps_macs);
1343 client->number_of_mps_macs = 0;
1344 client->mps_macs = kmalloc(ETH_ALEN,GFP_KERNEL);
1345 if (client->mps_macs == NULL) {
1346 printk("mpoa: set_mps_mac_addr_rcvd: out of memory\n");
1347 return;
1348 }
1349 client->number_of_mps_macs = 1;
1350 memcpy(client->mps_macs, msg->MPS_ctrl, ETH_ALEN);
1351
1352 return;
1353}
1354
1355/*
1356 * purge egress cache and tell daemon to 'action' (DIE, RELOAD)
1357 */
1358static void clean_up(struct k_message *msg, struct mpoa_client *mpc, int action)
1359{
1360
1361 eg_cache_entry *entry;
1362 msg->type = SND_EGRESS_PURGE;
1363
1364
1365 /* FIXME: This knows too much of the cache structure */
1366 read_lock_irq(&mpc->egress_lock);
1367 entry = mpc->eg_cache;
1368 while (entry != NULL){
1369 msg->content.eg_info = entry->ctrl_info;
1370 dprintk("mpoa: cache_id %u\n", entry->ctrl_info.cache_id);
1371 msg_to_mpoad(msg, mpc);
1372 entry = entry->next;
1373 }
1374 read_unlock_irq(&mpc->egress_lock);
1375
1376 msg->type = action;
1377 msg_to_mpoad(msg, mpc);
1378 return;
1379}
1380
1381static void mpc_timer_refresh(void)
1382{
1383 mpc_timer.expires = jiffies + (MPC_P2 * HZ);
1384 mpc_timer.data = mpc_timer.expires;
1385 mpc_timer.function = mpc_cache_check;
1386 add_timer(&mpc_timer);
1387
1388 return;
1389}
1390
1391static void mpc_cache_check( unsigned long checking_time )
1392{
1393 struct mpoa_client *mpc = mpcs;
1394 static unsigned long previous_resolving_check_time;
1395 static unsigned long previous_refresh_time;
1396
1397 while( mpc != NULL ){
1398 mpc->in_ops->clear_count(mpc);
1399 mpc->eg_ops->clear_expired(mpc);
1400 if(checking_time - previous_resolving_check_time > mpc->parameters.mpc_p4 * HZ ){
1401 mpc->in_ops->check_resolving(mpc);
1402 previous_resolving_check_time = checking_time;
1403 }
1404 if(checking_time - previous_refresh_time > mpc->parameters.mpc_p5 * HZ ){
1405 mpc->in_ops->refresh(mpc);
1406 previous_refresh_time = checking_time;
1407 }
1408 mpc = mpc->next;
1409 }
1410 mpc_timer_refresh();
1411
1412 return;
1413}
1414
1415static int atm_mpoa_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
1416{
1417 int err = 0;
1418 struct atm_vcc *vcc = ATM_SD(sock);
1419
1420 if (cmd != ATMMPC_CTRL && cmd != ATMMPC_DATA)
1421 return -ENOIOCTLCMD;
1422
1423 if (!capable(CAP_NET_ADMIN))
1424 return -EPERM;
1425
1426 switch (cmd) {
1427 case ATMMPC_CTRL:
1428 err = atm_mpoa_mpoad_attach(vcc, (int)arg);
1429 if (err >= 0)
1430 sock->state = SS_CONNECTED;
1431 break;
1432 case ATMMPC_DATA:
1433 err = atm_mpoa_vcc_attach(vcc, (void __user *)arg);
1434 break;
1435 default:
1436 break;
1437 }
1438 return err;
1439}
1440
1441
1442static struct atm_ioctl atm_ioctl_ops = {
1443 .owner = THIS_MODULE,
1444 .ioctl = atm_mpoa_ioctl,
1445};
1446
1447static __init int atm_mpoa_init(void)
1448{
1449 register_atm_ioctl(&atm_ioctl_ops);
1450
1451#ifdef CONFIG_PROC_FS
1452 if (mpc_proc_init() != 0)
1453 printk(KERN_INFO "mpoa: failed to initialize /proc/mpoa\n");
1454 else
1455 printk(KERN_INFO "mpoa: /proc/mpoa initialized\n");
1456#endif
1457
1458 printk("mpc.c: " __DATE__ " " __TIME__ " initialized\n");
1459
1460 return 0;
1461}
1462
1463static void __exit atm_mpoa_cleanup(void)
1464{
1465 struct mpoa_client *mpc, *tmp;
1466 struct atm_mpoa_qos *qos, *nextqos;
1467 struct lec_priv *priv;
1468
1469#ifdef CONFIG_PROC_FS
1470 mpc_proc_clean();
1471#endif
1472
1473 del_timer(&mpc_timer);
1474 unregister_netdevice_notifier(&mpoa_notifier);
1475 deregister_atm_ioctl(&atm_ioctl_ops);
1476
1477 mpc = mpcs;
1478 mpcs = NULL;
1479 while (mpc != NULL) {
1480 tmp = mpc->next;
1481 if (mpc->dev != NULL) {
1482 stop_mpc(mpc);
1483 priv = (struct lec_priv *)mpc->dev->priv;
1484 if (priv->lane2_ops != NULL)
1485 priv->lane2_ops->associate_indicator = NULL;
1486 }
1487 ddprintk("mpoa: cleanup_module: about to clear caches\n");
1488 mpc->in_ops->destroy_cache(mpc);
1489 mpc->eg_ops->destroy_cache(mpc);
1490 ddprintk("mpoa: cleanup_module: caches cleared\n");
1491 kfree(mpc->mps_macs);
1492 memset(mpc, 0, sizeof(struct mpoa_client));
1493 ddprintk("mpoa: cleanup_module: about to kfree %p\n", mpc);
1494 kfree(mpc);
1495 ddprintk("mpoa: cleanup_module: next mpc is at %p\n", tmp);
1496 mpc = tmp;
1497 }
1498
1499 qos = qos_head;
1500 qos_head = NULL;
1501 while (qos != NULL) {
1502 nextqos = qos->next;
1503 dprintk("mpoa: cleanup_module: freeing qos entry %p\n", qos);
1504 kfree(qos);
1505 qos = nextqos;
1506 }
1507
1508 return;
1509}
1510
1511module_init(atm_mpoa_init);
1512module_exit(atm_mpoa_cleanup);
1513
1514MODULE_LICENSE("GPL");
diff --git a/net/atm/mpc.h b/net/atm/mpc.h
new file mode 100644
index 000000000000..863ddf6079e1
--- /dev/null
+++ b/net/atm/mpc.h
@@ -0,0 +1,53 @@
1#ifndef _MPC_H_
2#define _MPC_H_
3
4#include <linux/types.h>
5#include <linux/atm.h>
6#include <linux/atmmpc.h>
7#include <linux/skbuff.h>
8#include <linux/spinlock.h>
9#include "mpoa_caches.h"
10
11/* kernel -> mpc-daemon */
12int msg_to_mpoad(struct k_message *msg, struct mpoa_client *mpc);
13
14struct mpoa_client {
15 struct mpoa_client *next;
16 struct net_device *dev; /* lec in question */
17 int dev_num; /* e.g. 2 for lec2 */
18 int (*old_hard_start_xmit)(struct sk_buff *skb, struct net_device *dev);
19 struct atm_vcc *mpoad_vcc; /* control channel to mpoad */
20 uint8_t mps_ctrl_addr[ATM_ESA_LEN]; /* MPS control ATM address */
21 uint8_t our_ctrl_addr[ATM_ESA_LEN]; /* MPC's control ATM address */
22
23 rwlock_t ingress_lock;
24 struct in_cache_ops *in_ops; /* ingress cache operations */
25 in_cache_entry *in_cache; /* the ingress cache of this MPC */
26
27 rwlock_t egress_lock;
28 struct eg_cache_ops *eg_ops; /* egress cache operations */
29 eg_cache_entry *eg_cache; /* the egress cache of this MPC */
30
31 uint8_t *mps_macs; /* array of MPS MAC addresses, >=1 */
32 int number_of_mps_macs; /* number of the above MAC addresses */
33 struct mpc_parameters parameters; /* parameters for this client */
34};
35
36
37struct atm_mpoa_qos {
38 struct atm_mpoa_qos *next;
39 uint32_t ipaddr;
40 struct atm_qos qos;
41};
42
43
44/* MPOA QoS operations */
45struct atm_mpoa_qos *atm_mpoa_add_qos(uint32_t dst_ip, struct atm_qos *qos);
46struct atm_mpoa_qos *atm_mpoa_search_qos(uint32_t dst_ip);
47int atm_mpoa_delete_qos(struct atm_mpoa_qos *qos);
48
49/* Display QoS entries. This is for the procfs */
50struct seq_file;
51void atm_mpoa_disp_qos(struct seq_file *m);
52
53#endif /* _MPC_H_ */
diff --git a/net/atm/mpoa_caches.c b/net/atm/mpoa_caches.c
new file mode 100644
index 000000000000..64ddebb64060
--- /dev/null
+++ b/net/atm/mpoa_caches.c
@@ -0,0 +1,576 @@
1#include <linux/types.h>
2#include <linux/atmmpc.h>
3#include <linux/time.h>
4
5#include "mpoa_caches.h"
6#include "mpc.h"
7
8/*
9 * mpoa_caches.c: Implementation of ingress and egress cache
10 * handling functions
11 */
12
13#if 0
14#define dprintk printk /* debug */
15#else
16#define dprintk(format,args...)
17#endif
18
19#if 0
20#define ddprintk printk /* more debug */
21#else
22#define ddprintk(format,args...)
23#endif
24
25static in_cache_entry *in_cache_get(uint32_t dst_ip,
26 struct mpoa_client *client)
27{
28 in_cache_entry *entry;
29
30 read_lock_bh(&client->ingress_lock);
31 entry = client->in_cache;
32 while(entry != NULL){
33 if( entry->ctrl_info.in_dst_ip == dst_ip ){
34 atomic_inc(&entry->use);
35 read_unlock_bh(&client->ingress_lock);
36 return entry;
37 }
38 entry = entry->next;
39 }
40 read_unlock_bh(&client->ingress_lock);
41
42 return NULL;
43}
44
45static in_cache_entry *in_cache_get_with_mask(uint32_t dst_ip,
46 struct mpoa_client *client,
47 uint32_t mask)
48{
49 in_cache_entry *entry;
50
51 read_lock_bh(&client->ingress_lock);
52 entry = client->in_cache;
53 while(entry != NULL){
54 if((entry->ctrl_info.in_dst_ip & mask) == (dst_ip & mask )){
55 atomic_inc(&entry->use);
56 read_unlock_bh(&client->ingress_lock);
57 return entry;
58 }
59 entry = entry->next;
60 }
61 read_unlock_bh(&client->ingress_lock);
62
63 return NULL;
64
65}
66
67static in_cache_entry *in_cache_get_by_vcc(struct atm_vcc *vcc,
68 struct mpoa_client *client )
69{
70 in_cache_entry *entry;
71
72 read_lock_bh(&client->ingress_lock);
73 entry = client->in_cache;
74 while(entry != NULL){
75 if(entry->shortcut == vcc) {
76 atomic_inc(&entry->use);
77 read_unlock_bh(&client->ingress_lock);
78 return entry;
79 }
80 entry = entry->next;
81 }
82 read_unlock_bh(&client->ingress_lock);
83
84 return NULL;
85}
86
87static in_cache_entry *in_cache_add_entry(uint32_t dst_ip,
88 struct mpoa_client *client)
89{
90 unsigned char *ip __attribute__ ((unused)) = (unsigned char *)&dst_ip;
91 in_cache_entry* entry = kmalloc(sizeof(in_cache_entry), GFP_KERNEL);
92
93 if (entry == NULL) {
94 printk("mpoa: mpoa_caches.c: new_in_cache_entry: out of memory\n");
95 return NULL;
96 }
97
98 dprintk("mpoa: mpoa_caches.c: adding an ingress entry, ip = %u.%u.%u.%u\n", ip[0], ip[1], ip[2], ip[3]);
99 memset(entry,0,sizeof(in_cache_entry));
100
101 atomic_set(&entry->use, 1);
102 dprintk("mpoa: mpoa_caches.c: new_in_cache_entry: about to lock\n");
103 write_lock_bh(&client->ingress_lock);
104 entry->next = client->in_cache;
105 entry->prev = NULL;
106 if (client->in_cache != NULL)
107 client->in_cache->prev = entry;
108 client->in_cache = entry;
109
110 memcpy(entry->MPS_ctrl_ATM_addr, client->mps_ctrl_addr, ATM_ESA_LEN);
111 entry->ctrl_info.in_dst_ip = dst_ip;
112 do_gettimeofday(&(entry->tv));
113 entry->retry_time = client->parameters.mpc_p4;
114 entry->count = 1;
115 entry->entry_state = INGRESS_INVALID;
116 entry->ctrl_info.holding_time = HOLDING_TIME_DEFAULT;
117 atomic_inc(&entry->use);
118
119 write_unlock_bh(&client->ingress_lock);
120 dprintk("mpoa: mpoa_caches.c: new_in_cache_entry: unlocked\n");
121
122 return entry;
123}
124
125static int cache_hit(in_cache_entry *entry, struct mpoa_client *mpc)
126{
127 struct atm_mpoa_qos *qos;
128 struct k_message msg;
129
130 entry->count++;
131 if(entry->entry_state == INGRESS_RESOLVED && entry->shortcut != NULL)
132 return OPEN;
133
134 if(entry->entry_state == INGRESS_REFRESHING){
135 if(entry->count > mpc->parameters.mpc_p1){
136 msg.type = SND_MPOA_RES_RQST;
137 msg.content.in_info = entry->ctrl_info;
138 memcpy(msg.MPS_ctrl, mpc->mps_ctrl_addr, ATM_ESA_LEN);
139 qos = atm_mpoa_search_qos(entry->ctrl_info.in_dst_ip);
140 if (qos != NULL) msg.qos = qos->qos;
141 msg_to_mpoad(&msg, mpc);
142 do_gettimeofday(&(entry->reply_wait));
143 entry->entry_state = INGRESS_RESOLVING;
144 }
145 if(entry->shortcut != NULL)
146 return OPEN;
147 return CLOSED;
148 }
149
150 if(entry->entry_state == INGRESS_RESOLVING && entry->shortcut != NULL)
151 return OPEN;
152
153 if( entry->count > mpc->parameters.mpc_p1 &&
154 entry->entry_state == INGRESS_INVALID){
155 unsigned char *ip __attribute__ ((unused)) =
156 (unsigned char *)&entry->ctrl_info.in_dst_ip;
157
158 dprintk("mpoa: (%s) mpoa_caches.c: threshold exceeded for ip %u.%u.%u.%u, sending MPOA res req\n", mpc->dev->name, ip[0], ip[1], ip[2], ip[3]);
159 entry->entry_state = INGRESS_RESOLVING;
160 msg.type = SND_MPOA_RES_RQST;
161 memcpy(msg.MPS_ctrl, mpc->mps_ctrl_addr, ATM_ESA_LEN );
162 msg.content.in_info = entry->ctrl_info;
163 qos = atm_mpoa_search_qos(entry->ctrl_info.in_dst_ip);
164 if (qos != NULL) msg.qos = qos->qos;
165 msg_to_mpoad( &msg, mpc);
166 do_gettimeofday(&(entry->reply_wait));
167 }
168
169 return CLOSED;
170}
171
172static void in_cache_put(in_cache_entry *entry)
173{
174 if (atomic_dec_and_test(&entry->use)) {
175 memset(entry, 0, sizeof(in_cache_entry));
176 kfree(entry);
177 }
178
179 return;
180}
181
182/*
183 * This should be called with write lock on
184 */
185static void in_cache_remove_entry(in_cache_entry *entry,
186 struct mpoa_client *client)
187{
188 struct atm_vcc *vcc;
189 struct k_message msg;
190 unsigned char *ip;
191
192 vcc = entry->shortcut;
193 ip = (unsigned char *)&entry->ctrl_info.in_dst_ip;
194 dprintk("mpoa: mpoa_caches.c: removing an ingress entry, ip = %u.%u.%u.%u\n",ip[0], ip[1], ip[2], ip[3]);
195
196 if (entry->prev != NULL)
197 entry->prev->next = entry->next;
198 else
199 client->in_cache = entry->next;
200 if (entry->next != NULL)
201 entry->next->prev = entry->prev;
202 client->in_ops->put(entry);
203 if(client->in_cache == NULL && client->eg_cache == NULL){
204 msg.type = STOP_KEEP_ALIVE_SM;
205 msg_to_mpoad(&msg,client);
206 }
207
208 /* Check if the egress side still uses this VCC */
209 if (vcc != NULL) {
210 eg_cache_entry *eg_entry = client->eg_ops->get_by_vcc(vcc, client);
211 if (eg_entry != NULL) {
212 client->eg_ops->put(eg_entry);
213 return;
214 }
215 vcc_release_async(vcc, -EPIPE);
216 }
217
218 return;
219}
220
221
222/* Call this every MPC-p2 seconds... Not exactly correct solution,
223 but an easy one... */
224static void clear_count_and_expired(struct mpoa_client *client)
225{
226 unsigned char *ip;
227 in_cache_entry *entry, *next_entry;
228 struct timeval now;
229
230 do_gettimeofday(&now);
231
232 write_lock_bh(&client->ingress_lock);
233 entry = client->in_cache;
234 while(entry != NULL){
235 entry->count=0;
236 next_entry = entry->next;
237 if((now.tv_sec - entry->tv.tv_sec)
238 > entry->ctrl_info.holding_time){
239 ip = (unsigned char*)&entry->ctrl_info.in_dst_ip;
240 dprintk("mpoa: mpoa_caches.c: holding time expired, ip = %u.%u.%u.%u\n", NIPQUAD(ip));
241 client->in_ops->remove_entry(entry, client);
242 }
243 entry = next_entry;
244 }
245 write_unlock_bh(&client->ingress_lock);
246
247 return;
248}
249
250/* Call this every MPC-p4 seconds. */
251static void check_resolving_entries(struct mpoa_client *client)
252{
253
254 struct atm_mpoa_qos *qos;
255 in_cache_entry *entry;
256 struct timeval now;
257 struct k_message msg;
258
259 do_gettimeofday( &now );
260
261 read_lock_bh(&client->ingress_lock);
262 entry = client->in_cache;
263 while( entry != NULL ){
264 if(entry->entry_state == INGRESS_RESOLVING){
265 if(now.tv_sec - entry->hold_down.tv_sec < client->parameters.mpc_p6){
266 entry = entry->next; /* Entry in hold down */
267 continue;
268 }
269 if( (now.tv_sec - entry->reply_wait.tv_sec) >
270 entry->retry_time ){
271 entry->retry_time = MPC_C1*( entry->retry_time );
272 if(entry->retry_time > client->parameters.mpc_p5){
273 /* Retry time maximum exceeded, put entry in hold down. */
274 do_gettimeofday(&(entry->hold_down));
275 entry->retry_time = client->parameters.mpc_p4;
276 entry = entry->next;
277 continue;
278 }
279 /* Ask daemon to send a resolution request. */
280 memset(&(entry->hold_down),0,sizeof(struct timeval));
281 msg.type = SND_MPOA_RES_RTRY;
282 memcpy(msg.MPS_ctrl, client->mps_ctrl_addr, ATM_ESA_LEN);
283 msg.content.in_info = entry->ctrl_info;
284 qos = atm_mpoa_search_qos(entry->ctrl_info.in_dst_ip);
285 if (qos != NULL) msg.qos = qos->qos;
286 msg_to_mpoad(&msg, client);
287 do_gettimeofday(&(entry->reply_wait));
288 }
289 }
290 entry = entry->next;
291 }
292 read_unlock_bh(&client->ingress_lock);
293}
294
295/* Call this every MPC-p5 seconds. */
296static void refresh_entries(struct mpoa_client *client)
297{
298 struct timeval now;
299 struct in_cache_entry *entry = client->in_cache;
300
301 ddprintk("mpoa: mpoa_caches.c: refresh_entries\n");
302 do_gettimeofday(&now);
303
304 read_lock_bh(&client->ingress_lock);
305 while( entry != NULL ){
306 if( entry->entry_state == INGRESS_RESOLVED ){
307 if(!(entry->refresh_time))
308 entry->refresh_time = (2*(entry->ctrl_info.holding_time))/3;
309 if( (now.tv_sec - entry->reply_wait.tv_sec) > entry->refresh_time ){
310 dprintk("mpoa: mpoa_caches.c: refreshing an entry.\n");
311 entry->entry_state = INGRESS_REFRESHING;
312
313 }
314 }
315 entry = entry->next;
316 }
317 read_unlock_bh(&client->ingress_lock);
318}
319
320static void in_destroy_cache(struct mpoa_client *mpc)
321{
322 write_lock_irq(&mpc->ingress_lock);
323 while(mpc->in_cache != NULL)
324 mpc->in_ops->remove_entry(mpc->in_cache, mpc);
325 write_unlock_irq(&mpc->ingress_lock);
326
327 return;
328}
329
330static eg_cache_entry *eg_cache_get_by_cache_id(uint32_t cache_id, struct mpoa_client *mpc)
331{
332 eg_cache_entry *entry;
333
334 read_lock_irq(&mpc->egress_lock);
335 entry = mpc->eg_cache;
336 while(entry != NULL){
337 if(entry->ctrl_info.cache_id == cache_id){
338 atomic_inc(&entry->use);
339 read_unlock_irq(&mpc->egress_lock);
340 return entry;
341 }
342 entry = entry->next;
343 }
344 read_unlock_irq(&mpc->egress_lock);
345
346 return NULL;
347}
348
349/* This can be called from any context since it saves CPU flags */
350static eg_cache_entry *eg_cache_get_by_tag(uint32_t tag, struct mpoa_client *mpc)
351{
352 unsigned long flags;
353 eg_cache_entry *entry;
354
355 read_lock_irqsave(&mpc->egress_lock, flags);
356 entry = mpc->eg_cache;
357 while (entry != NULL){
358 if (entry->ctrl_info.tag == tag) {
359 atomic_inc(&entry->use);
360 read_unlock_irqrestore(&mpc->egress_lock, flags);
361 return entry;
362 }
363 entry = entry->next;
364 }
365 read_unlock_irqrestore(&mpc->egress_lock, flags);
366
367 return NULL;
368}
369
370/* This can be called from any context since it saves CPU flags */
371static eg_cache_entry *eg_cache_get_by_vcc(struct atm_vcc *vcc, struct mpoa_client *mpc)
372{
373 unsigned long flags;
374 eg_cache_entry *entry;
375
376 read_lock_irqsave(&mpc->egress_lock, flags);
377 entry = mpc->eg_cache;
378 while (entry != NULL){
379 if (entry->shortcut == vcc) {
380 atomic_inc(&entry->use);
381 read_unlock_irqrestore(&mpc->egress_lock, flags);
382 return entry;
383 }
384 entry = entry->next;
385 }
386 read_unlock_irqrestore(&mpc->egress_lock, flags);
387
388 return NULL;
389}
390
391static eg_cache_entry *eg_cache_get_by_src_ip(uint32_t ipaddr, struct mpoa_client *mpc)
392{
393 eg_cache_entry *entry;
394
395 read_lock_irq(&mpc->egress_lock);
396 entry = mpc->eg_cache;
397 while(entry != NULL){
398 if(entry->latest_ip_addr == ipaddr) {
399 atomic_inc(&entry->use);
400 read_unlock_irq(&mpc->egress_lock);
401 return entry;
402 }
403 entry = entry->next;
404 }
405 read_unlock_irq(&mpc->egress_lock);
406
407 return NULL;
408}
409
410static void eg_cache_put(eg_cache_entry *entry)
411{
412 if (atomic_dec_and_test(&entry->use)) {
413 memset(entry, 0, sizeof(eg_cache_entry));
414 kfree(entry);
415 }
416
417 return;
418}
419
420/*
421 * This should be called with write lock on
422 */
423static void eg_cache_remove_entry(eg_cache_entry *entry,
424 struct mpoa_client *client)
425{
426 struct atm_vcc *vcc;
427 struct k_message msg;
428
429 vcc = entry->shortcut;
430 dprintk("mpoa: mpoa_caches.c: removing an egress entry.\n");
431 if (entry->prev != NULL)
432 entry->prev->next = entry->next;
433 else
434 client->eg_cache = entry->next;
435 if (entry->next != NULL)
436 entry->next->prev = entry->prev;
437 client->eg_ops->put(entry);
438 if(client->in_cache == NULL && client->eg_cache == NULL){
439 msg.type = STOP_KEEP_ALIVE_SM;
440 msg_to_mpoad(&msg,client);
441 }
442
443 /* Check if the ingress side still uses this VCC */
444 if (vcc != NULL) {
445 in_cache_entry *in_entry = client->in_ops->get_by_vcc(vcc, client);
446 if (in_entry != NULL) {
447 client->in_ops->put(in_entry);
448 return;
449 }
450 vcc_release_async(vcc, -EPIPE);
451 }
452
453 return;
454}
455
456static eg_cache_entry *eg_cache_add_entry(struct k_message *msg, struct mpoa_client *client)
457{
458 unsigned char *ip;
459 eg_cache_entry *entry = kmalloc(sizeof(eg_cache_entry), GFP_KERNEL);
460
461 if (entry == NULL) {
462 printk("mpoa: mpoa_caches.c: new_eg_cache_entry: out of memory\n");
463 return NULL;
464 }
465
466 ip = (unsigned char *)&msg->content.eg_info.eg_dst_ip;
467 dprintk("mpoa: mpoa_caches.c: adding an egress entry, ip = %u.%u.%u.%u, this should be our IP\n", NIPQUAD(ip));
468 memset(entry, 0, sizeof(eg_cache_entry));
469
470 atomic_set(&entry->use, 1);
471 dprintk("mpoa: mpoa_caches.c: new_eg_cache_entry: about to lock\n");
472 write_lock_irq(&client->egress_lock);
473 entry->next = client->eg_cache;
474 entry->prev = NULL;
475 if (client->eg_cache != NULL)
476 client->eg_cache->prev = entry;
477 client->eg_cache = entry;
478
479 memcpy(entry->MPS_ctrl_ATM_addr, client->mps_ctrl_addr, ATM_ESA_LEN);
480 entry->ctrl_info = msg->content.eg_info;
481 do_gettimeofday(&(entry->tv));
482 entry->entry_state = EGRESS_RESOLVED;
483 dprintk("mpoa: mpoa_caches.c: new_eg_cache_entry cache_id %lu\n", ntohl(entry->ctrl_info.cache_id));
484 ip = (unsigned char *)&entry->ctrl_info.mps_ip;
485 dprintk("mpoa: mpoa_caches.c: mps_ip = %u.%u.%u.%u\n", NIPQUAD(ip));
486 atomic_inc(&entry->use);
487
488 write_unlock_irq(&client->egress_lock);
489 dprintk("mpoa: mpoa_caches.c: new_eg_cache_entry: unlocked\n");
490
491 return entry;
492}
493
494static void update_eg_cache_entry(eg_cache_entry * entry, uint16_t holding_time)
495{
496 do_gettimeofday(&(entry->tv));
497 entry->entry_state = EGRESS_RESOLVED;
498 entry->ctrl_info.holding_time = holding_time;
499
500 return;
501}
502
503static void clear_expired(struct mpoa_client *client)
504{
505 eg_cache_entry *entry, *next_entry;
506 struct timeval now;
507 struct k_message msg;
508
509 do_gettimeofday(&now);
510
511 write_lock_irq(&client->egress_lock);
512 entry = client->eg_cache;
513 while(entry != NULL){
514 next_entry = entry->next;
515 if((now.tv_sec - entry->tv.tv_sec)
516 > entry->ctrl_info.holding_time){
517 msg.type = SND_EGRESS_PURGE;
518 msg.content.eg_info = entry->ctrl_info;
519 dprintk("mpoa: mpoa_caches.c: egress_cache: holding time expired, cache_id = %lu.\n",ntohl(entry->ctrl_info.cache_id));
520 msg_to_mpoad(&msg, client);
521 client->eg_ops->remove_entry(entry, client);
522 }
523 entry = next_entry;
524 }
525 write_unlock_irq(&client->egress_lock);
526
527 return;
528}
529
530static void eg_destroy_cache(struct mpoa_client *mpc)
531{
532 write_lock_irq(&mpc->egress_lock);
533 while(mpc->eg_cache != NULL)
534 mpc->eg_ops->remove_entry(mpc->eg_cache, mpc);
535 write_unlock_irq(&mpc->egress_lock);
536
537 return;
538}
539
540
541
542static struct in_cache_ops ingress_ops = {
543 in_cache_add_entry, /* add_entry */
544 in_cache_get, /* get */
545 in_cache_get_with_mask, /* get_with_mask */
546 in_cache_get_by_vcc, /* get_by_vcc */
547 in_cache_put, /* put */
548 in_cache_remove_entry, /* remove_entry */
549 cache_hit, /* cache_hit */
550 clear_count_and_expired, /* clear_count */
551 check_resolving_entries, /* check_resolving */
552 refresh_entries, /* refresh */
553 in_destroy_cache /* destroy_cache */
554};
555
556static struct eg_cache_ops egress_ops = {
557 eg_cache_add_entry, /* add_entry */
558 eg_cache_get_by_cache_id, /* get_by_cache_id */
559 eg_cache_get_by_tag, /* get_by_tag */
560 eg_cache_get_by_vcc, /* get_by_vcc */
561 eg_cache_get_by_src_ip, /* get_by_src_ip */
562 eg_cache_put, /* put */
563 eg_cache_remove_entry, /* remove_entry */
564 update_eg_cache_entry, /* update */
565 clear_expired, /* clear_expired */
566 eg_destroy_cache /* destroy_cache */
567};
568
569
570void atm_mpoa_init_cache(struct mpoa_client *mpc)
571{
572 mpc->in_ops = &ingress_ops;
573 mpc->eg_ops = &egress_ops;
574
575 return;
576}
diff --git a/net/atm/mpoa_caches.h b/net/atm/mpoa_caches.h
new file mode 100644
index 000000000000..6c9886a03d0b
--- /dev/null
+++ b/net/atm/mpoa_caches.h
@@ -0,0 +1,96 @@
1#ifndef MPOA_CACHES_H
2#define MPOA_CACHES_H
3
4#include <linux/netdevice.h>
5#include <linux/types.h>
6#include <linux/atm.h>
7#include <linux/atmdev.h>
8#include <linux/atmmpc.h>
9
10struct mpoa_client;
11
12void atm_mpoa_init_cache(struct mpoa_client *mpc);
13
14typedef struct in_cache_entry {
15 struct in_cache_entry *next;
16 struct in_cache_entry *prev;
17 struct timeval tv;
18 struct timeval reply_wait;
19 struct timeval hold_down;
20 uint32_t packets_fwded;
21 uint16_t entry_state;
22 uint32_t retry_time;
23 uint32_t refresh_time;
24 uint32_t count;
25 struct atm_vcc *shortcut;
26 uint8_t MPS_ctrl_ATM_addr[ATM_ESA_LEN];
27 struct in_ctrl_info ctrl_info;
28 atomic_t use;
29} in_cache_entry;
30
31struct in_cache_ops{
32 in_cache_entry *(*add_entry)(uint32_t dst_ip,
33 struct mpoa_client *client);
34 in_cache_entry *(*get)(uint32_t dst_ip, struct mpoa_client *client);
35 in_cache_entry *(*get_with_mask)(uint32_t dst_ip,
36 struct mpoa_client *client,
37 uint32_t mask);
38 in_cache_entry *(*get_by_vcc)(struct atm_vcc *vcc,
39 struct mpoa_client *client);
40 void (*put)(in_cache_entry *entry);
41 void (*remove_entry)(in_cache_entry *delEntry,
42 struct mpoa_client *client );
43 int (*cache_hit)(in_cache_entry *entry,
44 struct mpoa_client *client);
45 void (*clear_count)(struct mpoa_client *client);
46 void (*check_resolving)(struct mpoa_client *client);
47 void (*refresh)(struct mpoa_client *client);
48 void (*destroy_cache)(struct mpoa_client *mpc);
49};
50
51typedef struct eg_cache_entry{
52 struct eg_cache_entry *next;
53 struct eg_cache_entry *prev;
54 struct timeval tv;
55 uint8_t MPS_ctrl_ATM_addr[ATM_ESA_LEN];
56 struct atm_vcc *shortcut;
57 uint32_t packets_rcvd;
58 uint16_t entry_state;
59 uint32_t latest_ip_addr; /* The src IP address of the last packet */
60 struct eg_ctrl_info ctrl_info;
61 atomic_t use;
62} eg_cache_entry;
63
64struct eg_cache_ops{
65 eg_cache_entry *(*add_entry)(struct k_message *msg, struct mpoa_client *client);
66 eg_cache_entry *(*get_by_cache_id)(uint32_t cache_id, struct mpoa_client *client);
67 eg_cache_entry *(*get_by_tag)(uint32_t cache_id, struct mpoa_client *client);
68 eg_cache_entry *(*get_by_vcc)(struct atm_vcc *vcc, struct mpoa_client *client);
69 eg_cache_entry *(*get_by_src_ip)(uint32_t ipaddr, struct mpoa_client *client);
70 void (*put)(eg_cache_entry *entry);
71 void (*remove_entry)(eg_cache_entry *entry, struct mpoa_client *client);
72 void (*update)(eg_cache_entry *entry, uint16_t holding_time);
73 void (*clear_expired)(struct mpoa_client *client);
74 void (*destroy_cache)(struct mpoa_client *mpc);
75};
76
77
78/* Ingress cache entry states */
79
80#define INGRESS_REFRESHING 3
81#define INGRESS_RESOLVED 2
82#define INGRESS_RESOLVING 1
83#define INGRESS_INVALID 0
84
85/* VCC states */
86
87#define OPEN 1
88#define CLOSED 0
89
90/* Egress cache entry states */
91
92#define EGRESS_RESOLVED 2
93#define EGRESS_PURGE 1
94#define EGRESS_INVALID 0
95
96#endif
diff --git a/net/atm/mpoa_proc.c b/net/atm/mpoa_proc.c
new file mode 100644
index 000000000000..60834b5a14d6
--- /dev/null
+++ b/net/atm/mpoa_proc.c
@@ -0,0 +1,305 @@
1#include <linux/config.h>
2
3#ifdef CONFIG_PROC_FS
4#include <linux/errno.h>
5#include <linux/kernel.h>
6#include <linux/string.h>
7#include <linux/mm.h>
8#include <linux/module.h>
9#include <linux/proc_fs.h>
10#include <linux/time.h>
11#include <linux/seq_file.h>
12#include <asm/uaccess.h>
13#include <linux/atmmpc.h>
14#include <linux/atm.h>
15#include "mpc.h"
16#include "mpoa_caches.h"
17
18/*
19 * mpoa_proc.c: Implementation MPOA client's proc
20 * file system statistics
21 */
22
23#if 1
24#define dprintk printk /* debug */
25#else
26#define dprintk(format,args...)
27#endif
28
29#define STAT_FILE_NAME "mpc" /* Our statistic file's name */
30
31extern struct mpoa_client *mpcs;
32extern struct proc_dir_entry *atm_proc_root; /* from proc.c. */
33
34static int proc_mpc_open(struct inode *inode, struct file *file);
35static ssize_t proc_mpc_write(struct file *file, const char __user *buff,
36 size_t nbytes, loff_t *ppos);
37
38static int parse_qos(const char *buff);
39
40/*
41 * Define allowed FILE OPERATIONS
42 */
43static struct file_operations mpc_file_operations = {
44 .owner = THIS_MODULE,
45 .open = proc_mpc_open,
46 .read = seq_read,
47 .llseek = seq_lseek,
48 .write = proc_mpc_write,
49 .release = seq_release,
50};
51
52/*
53 * Returns the state of an ingress cache entry as a string
54 */
55static const char *ingress_state_string(int state){
56 switch(state) {
57 case INGRESS_RESOLVING:
58 return "resolving ";
59 break;
60 case INGRESS_RESOLVED:
61 return "resolved ";
62 break;
63 case INGRESS_INVALID:
64 return "invalid ";
65 break;
66 case INGRESS_REFRESHING:
67 return "refreshing ";
68 break;
69 default:
70 return "";
71 }
72}
73
74/*
75 * Returns the state of an egress cache entry as a string
76 */
77static const char *egress_state_string(int state){
78 switch(state) {
79 case EGRESS_RESOLVED:
80 return "resolved ";
81 break;
82 case EGRESS_PURGE:
83 return "purge ";
84 break;
85 case EGRESS_INVALID:
86 return "invalid ";
87 break;
88 default:
89 return "";
90 }
91}
92
93/*
94 * FIXME: mpcs (and per-mpc lists) have no locking whatsoever.
95 */
96
97static void *mpc_start(struct seq_file *m, loff_t *pos)
98{
99 loff_t l = *pos;
100 struct mpoa_client *mpc;
101
102 if (!l--)
103 return SEQ_START_TOKEN;
104 for (mpc = mpcs; mpc; mpc = mpc->next)
105 if (!l--)
106 return mpc;
107 return NULL;
108}
109
110static void *mpc_next(struct seq_file *m, void *v, loff_t *pos)
111{
112 struct mpoa_client *p = v;
113 (*pos)++;
114 return v == SEQ_START_TOKEN ? mpcs : p->next;
115}
116
117static void mpc_stop(struct seq_file *m, void *v)
118{
119}
120
121/*
122 * READING function - called when the /proc/atm/mpoa file is read from.
123 */
124static int mpc_show(struct seq_file *m, void *v)
125{
126 struct mpoa_client *mpc = v;
127 unsigned char *temp;
128 int i;
129 in_cache_entry *in_entry;
130 eg_cache_entry *eg_entry;
131 struct timeval now;
132 unsigned char ip_string[16];
133
134 if (v == SEQ_START_TOKEN) {
135 atm_mpoa_disp_qos(m);
136 return 0;
137 }
138
139 seq_printf(m, "\nInterface %d:\n\n", mpc->dev_num);
140 seq_printf(m, "Ingress Entries:\nIP address State Holding time Packets fwded VPI VCI\n");
141 do_gettimeofday(&now);
142
143 for (in_entry = mpc->in_cache; in_entry; in_entry = in_entry->next) {
144 temp = (unsigned char *)&in_entry->ctrl_info.in_dst_ip;
145 sprintf(ip_string,"%d.%d.%d.%d", temp[0], temp[1], temp[2], temp[3]);
146 seq_printf(m, "%-16s%s%-14lu%-12u",
147 ip_string,
148 ingress_state_string(in_entry->entry_state),
149 in_entry->ctrl_info.holding_time-(now.tv_sec-in_entry->tv.tv_sec),
150 in_entry->packets_fwded);
151 if (in_entry->shortcut)
152 seq_printf(m, " %-3d %-3d",in_entry->shortcut->vpi,in_entry->shortcut->vci);
153 seq_printf(m, "\n");
154 }
155
156 seq_printf(m, "\n");
157 seq_printf(m, "Egress Entries:\nIngress MPC ATM addr\nCache-id State Holding time Packets recvd Latest IP addr VPI VCI\n");
158 for (eg_entry = mpc->eg_cache; eg_entry; eg_entry = eg_entry->next) {
159 unsigned char *p = eg_entry->ctrl_info.in_MPC_data_ATM_addr;
160 for(i = 0; i < ATM_ESA_LEN; i++)
161 seq_printf(m, "%02x", p[i]);
162 seq_printf(m, "\n%-16lu%s%-14lu%-15u",
163 (unsigned long)ntohl(eg_entry->ctrl_info.cache_id),
164 egress_state_string(eg_entry->entry_state),
165 (eg_entry->ctrl_info.holding_time-(now.tv_sec-eg_entry->tv.tv_sec)),
166 eg_entry->packets_rcvd);
167
168 /* latest IP address */
169 temp = (unsigned char *)&eg_entry->latest_ip_addr;
170 sprintf(ip_string, "%d.%d.%d.%d", temp[0], temp[1], temp[2], temp[3]);
171 seq_printf(m, "%-16s", ip_string);
172
173 if (eg_entry->shortcut)
174 seq_printf(m, " %-3d %-3d",eg_entry->shortcut->vpi,eg_entry->shortcut->vci);
175 seq_printf(m, "\n");
176 }
177 seq_printf(m, "\n");
178 return 0;
179}
180
181static struct seq_operations mpc_op = {
182 .start = mpc_start,
183 .next = mpc_next,
184 .stop = mpc_stop,
185 .show = mpc_show
186};
187
188static int proc_mpc_open(struct inode *inode, struct file *file)
189{
190 return seq_open(file, &mpc_op);
191}
192
193static ssize_t proc_mpc_write(struct file *file, const char __user *buff,
194 size_t nbytes, loff_t *ppos)
195{
196 char *page, *p;
197 unsigned len;
198
199 if (nbytes == 0)
200 return 0;
201
202 if (nbytes >= PAGE_SIZE)
203 nbytes = PAGE_SIZE-1;
204
205 page = (char *)__get_free_page(GFP_KERNEL);
206 if (!page)
207 return -ENOMEM;
208
209 for (p = page, len = 0; len < nbytes; p++, len++) {
210 if (get_user(*p, buff++)) {
211 free_page((unsigned long)page);
212 return -EFAULT;
213 }
214 if (*p == '\0' || *p == '\n')
215 break;
216 }
217
218 *p = '\0';
219
220 if (!parse_qos(page))
221 printk("mpoa: proc_mpc_write: could not parse '%s'\n", page);
222
223 free_page((unsigned long)page);
224
225 return len;
226}
227
228static int parse_qos(const char *buff)
229{
230 /* possible lines look like this
231 * add 130.230.54.142 tx=max_pcr,max_sdu rx=max_pcr,max_sdu
232 */
233 unsigned char ip[4];
234 int tx_pcr, tx_sdu, rx_pcr, rx_sdu;
235 uint32_t ipaddr;
236 struct atm_qos qos;
237
238 memset(&qos, 0, sizeof(struct atm_qos));
239
240 if (sscanf(buff, "del %hhu.%hhu.%hhu.%hhu",
241 ip, ip+1, ip+2, ip+3) == 4) {
242 ipaddr = *(uint32_t *)ip;
243 return atm_mpoa_delete_qos(atm_mpoa_search_qos(ipaddr));
244 }
245
246 if (sscanf(buff, "add %hhu.%hhu.%hhu.%hhu tx=%d,%d rx=tx",
247 ip, ip+1, ip+2, ip+3, &tx_pcr, &tx_sdu) == 6) {
248 rx_pcr = tx_pcr;
249 rx_sdu = tx_sdu;
250 } else if (sscanf(buff, "add %hhu.%hhu.%hhu.%hhu tx=%d,%d rx=%d,%d",
251 ip, ip+1, ip+2, ip+3, &tx_pcr, &tx_sdu, &rx_pcr, &rx_sdu) != 8)
252 return 0;
253
254 ipaddr = *(uint32_t *)ip;
255 qos.txtp.traffic_class = ATM_CBR;
256 qos.txtp.max_pcr = tx_pcr;
257 qos.txtp.max_sdu = tx_sdu;
258 qos.rxtp.traffic_class = ATM_CBR;
259 qos.rxtp.max_pcr = rx_pcr;
260 qos.rxtp.max_sdu = rx_sdu;
261 qos.aal = ATM_AAL5;
262 dprintk("mpoa: mpoa_proc.c: parse_qos(): setting qos paramameters to tx=%d,%d rx=%d,%d\n",
263 qos.txtp.max_pcr,
264 qos.txtp.max_sdu,
265 qos.rxtp.max_pcr,
266 qos.rxtp.max_sdu
267 );
268
269 atm_mpoa_add_qos(ipaddr, &qos);
270 return 1;
271}
272
273/*
274 * INITIALIZATION function - called when module is initialized/loaded.
275 */
276int mpc_proc_init(void)
277{
278 struct proc_dir_entry *p;
279
280 p = create_proc_entry(STAT_FILE_NAME, 0, atm_proc_root);
281 if (!p) {
282 printk(KERN_ERR "Unable to initialize /proc/atm/%s\n", STAT_FILE_NAME);
283 return -ENOMEM;
284 }
285 p->proc_fops = &mpc_file_operations;
286 p->owner = THIS_MODULE;
287 return 0;
288}
289
290/*
291 * DELETING function - called when module is removed.
292 */
293void mpc_proc_clean(void)
294{
295 remove_proc_entry(STAT_FILE_NAME,atm_proc_root);
296}
297
298
299#endif /* CONFIG_PROC_FS */
300
301
302
303
304
305
diff --git a/net/atm/pppoatm.c b/net/atm/pppoatm.c
new file mode 100644
index 000000000000..58f4a2b5aebe
--- /dev/null
+++ b/net/atm/pppoatm.c
@@ -0,0 +1,369 @@
1/* net/atm/pppoatm.c - RFC2364 PPP over ATM/AAL5 */
2
3/* Copyright 1999-2000 by Mitchell Blank Jr */
4/* Based on clip.c; 1995-1999 by Werner Almesberger, EPFL LRC/ICA */
5/* And on ppp_async.c; Copyright 1999 Paul Mackerras */
6/* And help from Jens Axboe */
7
8/*
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version
12 * 2 of the License, or (at your option) any later version.
13 *
14 * This driver provides the encapsulation and framing for sending
15 * and receiving PPP frames in ATM AAL5 PDUs.
16 */
17
18/*
19 * One shortcoming of this driver is that it does not comply with
20 * section 8 of RFC2364 - we are supposed to detect a change
21 * in encapsulation and immediately abort the connection (in order
22 * to avoid a black-hole being created if our peer loses state
23 * and changes encapsulation unilaterally. However, since the
24 * ppp_generic layer actually does the decapsulation, we need
25 * a way of notifying it when we _think_ there might be a problem)
26 * There's two cases:
27 * 1. LLC-encapsulation was missing when it was enabled. In
28 * this case, we should tell the upper layer "tear down
29 * this session if this skb looks ok to you"
30 * 2. LLC-encapsulation was present when it was disabled. Then
31 * we need to tell the upper layer "this packet may be
32 * ok, but if its in error tear down the session"
33 * These hooks are not yet available in ppp_generic
34 */
35
36#include <linux/module.h>
37#include <linux/config.h>
38#include <linux/init.h>
39#include <linux/skbuff.h>
40#include <linux/atm.h>
41#include <linux/atmdev.h>
42#include <linux/ppp_defs.h>
43#include <linux/if_ppp.h>
44#include <linux/ppp_channel.h>
45#include <linux/atmppp.h>
46
47#include "common.h"
48
49#if 0
50#define DPRINTK(format, args...) \
51 printk(KERN_DEBUG "pppoatm: " format, ##args)
52#else
53#define DPRINTK(format, args...)
54#endif
55
56enum pppoatm_encaps {
57 e_autodetect = PPPOATM_ENCAPS_AUTODETECT,
58 e_vc = PPPOATM_ENCAPS_VC,
59 e_llc = PPPOATM_ENCAPS_LLC,
60};
61
62struct pppoatm_vcc {
63 struct atm_vcc *atmvcc; /* VCC descriptor */
64 void (*old_push)(struct atm_vcc *, struct sk_buff *);
65 void (*old_pop)(struct atm_vcc *, struct sk_buff *);
66 /* keep old push/pop for detaching */
67 enum pppoatm_encaps encaps;
68 int flags; /* SC_COMP_PROT - compress protocol */
69 struct ppp_channel chan; /* interface to generic ppp layer */
70 struct tasklet_struct wakeup_tasklet;
71};
72
73/*
74 * Header used for LLC Encapsulated PPP (4 bytes) followed by the LCP protocol
75 * ID (0xC021) used in autodetection
76 */
77static const unsigned char pppllc[6] = { 0xFE, 0xFE, 0x03, 0xCF, 0xC0, 0x21 };
78#define LLC_LEN (4)
79
80static inline struct pppoatm_vcc *atmvcc_to_pvcc(const struct atm_vcc *atmvcc)
81{
82 return (struct pppoatm_vcc *) (atmvcc->user_back);
83}
84
85static inline struct pppoatm_vcc *chan_to_pvcc(const struct ppp_channel *chan)
86{
87 return (struct pppoatm_vcc *) (chan->private);
88}
89
90/*
91 * We can't do this directly from our _pop handler, since the ppp code
92 * doesn't want to be called in interrupt context, so we do it from
93 * a tasklet
94 */
95static void pppoatm_wakeup_sender(unsigned long arg)
96{
97 ppp_output_wakeup((struct ppp_channel *) arg);
98}
99
100/*
101 * This gets called every time the ATM card has finished sending our
102 * skb. The ->old_pop will take care up normal atm flow control,
103 * but we also need to wake up the device if we blocked it
104 */
105static void pppoatm_pop(struct atm_vcc *atmvcc, struct sk_buff *skb)
106{
107 struct pppoatm_vcc *pvcc = atmvcc_to_pvcc(atmvcc);
108 pvcc->old_pop(atmvcc, skb);
109 /*
110 * We don't really always want to do this since it's
111 * really inefficient - it would be much better if we could
112 * test if we had actually throttled the generic layer.
113 * Unfortunately then there would be a nasty SMP race where
114 * we could clear that flag just as we refuse another packet.
115 * For now we do the safe thing.
116 */
117 tasklet_schedule(&pvcc->wakeup_tasklet);
118}
119
120/*
121 * Unbind from PPP - currently we only do this when closing the socket,
122 * but we could put this into an ioctl if need be
123 */
124static void pppoatm_unassign_vcc(struct atm_vcc *atmvcc)
125{
126 struct pppoatm_vcc *pvcc;
127 pvcc = atmvcc_to_pvcc(atmvcc);
128 atmvcc->push = pvcc->old_push;
129 atmvcc->pop = pvcc->old_pop;
130 tasklet_kill(&pvcc->wakeup_tasklet);
131 ppp_unregister_channel(&pvcc->chan);
132 atmvcc->user_back = NULL;
133 kfree(pvcc);
134 /* Gee, I hope we have the big kernel lock here... */
135 module_put(THIS_MODULE);
136}
137
138/* Called when an AAL5 PDU comes in */
139static void pppoatm_push(struct atm_vcc *atmvcc, struct sk_buff *skb)
140{
141 struct pppoatm_vcc *pvcc = atmvcc_to_pvcc(atmvcc);
142 DPRINTK("pppoatm push\n");
143 if (skb == NULL) { /* VCC was closed */
144 DPRINTK("removing ATMPPP VCC %p\n", pvcc);
145 pppoatm_unassign_vcc(atmvcc);
146 atmvcc->push(atmvcc, NULL); /* Pass along bad news */
147 return;
148 }
149 atm_return(atmvcc, skb->truesize);
150 switch (pvcc->encaps) {
151 case e_llc:
152 if (skb->len < LLC_LEN ||
153 memcmp(skb->data, pppllc, LLC_LEN))
154 goto error;
155 skb_pull(skb, LLC_LEN);
156 break;
157 case e_autodetect:
158 if (pvcc->chan.ppp == NULL) { /* Not bound yet! */
159 kfree_skb(skb);
160 return;
161 }
162 if (skb->len >= sizeof(pppllc) &&
163 !memcmp(skb->data, pppllc, sizeof(pppllc))) {
164 pvcc->encaps = e_llc;
165 skb_pull(skb, LLC_LEN);
166 break;
167 }
168 if (skb->len >= (sizeof(pppllc) - LLC_LEN) &&
169 !memcmp(skb->data, &pppllc[LLC_LEN],
170 sizeof(pppllc) - LLC_LEN)) {
171 pvcc->encaps = e_vc;
172 pvcc->chan.mtu += LLC_LEN;
173 break;
174 }
175 DPRINTK("(unit %d): Couldn't autodetect yet "
176 "(skb: %02X %02X %02X %02X %02X %02X)\n",
177 pvcc->chan.unit,
178 skb->data[0], skb->data[1], skb->data[2],
179 skb->data[3], skb->data[4], skb->data[5]);
180 goto error;
181 case e_vc:
182 break;
183 }
184 ppp_input(&pvcc->chan, skb);
185 return;
186 error:
187 kfree_skb(skb);
188 ppp_input_error(&pvcc->chan, 0);
189}
190
191/*
192 * Called by the ppp_generic.c to send a packet - returns true if packet
193 * was accepted. If we return false, then it's our job to call
194 * ppp_output_wakeup(chan) when we're feeling more up to it.
195 * Note that in the ENOMEM case (as opposed to the !atm_may_send case)
196 * we should really drop the packet, but the generic layer doesn't
197 * support this yet. We just return 'DROP_PACKET' which we actually define
198 * as success, just to be clear what we're really doing.
199 */
200#define DROP_PACKET 1
201static int pppoatm_send(struct ppp_channel *chan, struct sk_buff *skb)
202{
203 struct pppoatm_vcc *pvcc = chan_to_pvcc(chan);
204 ATM_SKB(skb)->vcc = pvcc->atmvcc;
205 DPRINTK("(unit %d): pppoatm_send (skb=0x%p, vcc=0x%p)\n",
206 pvcc->chan.unit, skb, pvcc->atmvcc);
207 if (skb->data[0] == '\0' && (pvcc->flags & SC_COMP_PROT))
208 (void) skb_pull(skb, 1);
209 switch (pvcc->encaps) { /* LLC encapsulation needed */
210 case e_llc:
211 if (skb_headroom(skb) < LLC_LEN) {
212 struct sk_buff *n;
213 n = skb_realloc_headroom(skb, LLC_LEN);
214 if (n != NULL &&
215 !atm_may_send(pvcc->atmvcc, n->truesize)) {
216 kfree_skb(n);
217 goto nospace;
218 }
219 kfree_skb(skb);
220 if ((skb = n) == NULL)
221 return DROP_PACKET;
222 } else if (!atm_may_send(pvcc->atmvcc, skb->truesize))
223 goto nospace;
224 memcpy(skb_push(skb, LLC_LEN), pppllc, LLC_LEN);
225 break;
226 case e_vc:
227 if (!atm_may_send(pvcc->atmvcc, skb->truesize))
228 goto nospace;
229 break;
230 case e_autodetect:
231 DPRINTK("(unit %d): Trying to send without setting encaps!\n",
232 pvcc->chan.unit);
233 kfree_skb(skb);
234 return 1;
235 }
236
237 atomic_add(skb->truesize, &sk_atm(ATM_SKB(skb)->vcc)->sk_wmem_alloc);
238 ATM_SKB(skb)->atm_options = ATM_SKB(skb)->vcc->atm_options;
239 DPRINTK("(unit %d): atm_skb(%p)->vcc(%p)->dev(%p)\n",
240 pvcc->chan.unit, skb, ATM_SKB(skb)->vcc,
241 ATM_SKB(skb)->vcc->dev);
242 return ATM_SKB(skb)->vcc->send(ATM_SKB(skb)->vcc, skb)
243 ? DROP_PACKET : 1;
244 nospace:
245 /*
246 * We don't have space to send this SKB now, but we might have
247 * already applied SC_COMP_PROT compression, so may need to undo
248 */
249 if ((pvcc->flags & SC_COMP_PROT) && skb_headroom(skb) > 0 &&
250 skb->data[-1] == '\0')
251 (void) skb_push(skb, 1);
252 return 0;
253}
254
255/* This handles ioctls sent to the /dev/ppp interface */
256static int pppoatm_devppp_ioctl(struct ppp_channel *chan, unsigned int cmd,
257 unsigned long arg)
258{
259 switch (cmd) {
260 case PPPIOCGFLAGS:
261 return put_user(chan_to_pvcc(chan)->flags, (int __user *) arg)
262 ? -EFAULT : 0;
263 case PPPIOCSFLAGS:
264 return get_user(chan_to_pvcc(chan)->flags, (int __user *) arg)
265 ? -EFAULT : 0;
266 }
267 return -ENOTTY;
268}
269
270static /*const*/ struct ppp_channel_ops pppoatm_ops = {
271 .start_xmit = pppoatm_send,
272 .ioctl = pppoatm_devppp_ioctl,
273};
274
275static int pppoatm_assign_vcc(struct atm_vcc *atmvcc, void __user *arg)
276{
277 struct atm_backend_ppp be;
278 struct pppoatm_vcc *pvcc;
279 int err;
280 /*
281 * Each PPPoATM instance has its own tasklet - this is just a
282 * prototypical one used to initialize them
283 */
284 static const DECLARE_TASKLET(tasklet_proto, pppoatm_wakeup_sender, 0);
285 if (copy_from_user(&be, arg, sizeof be))
286 return -EFAULT;
287 if (be.encaps != PPPOATM_ENCAPS_AUTODETECT &&
288 be.encaps != PPPOATM_ENCAPS_VC && be.encaps != PPPOATM_ENCAPS_LLC)
289 return -EINVAL;
290 pvcc = kmalloc(sizeof(*pvcc), GFP_KERNEL);
291 if (pvcc == NULL)
292 return -ENOMEM;
293 memset(pvcc, 0, sizeof(*pvcc));
294 pvcc->atmvcc = atmvcc;
295 pvcc->old_push = atmvcc->push;
296 pvcc->old_pop = atmvcc->pop;
297 pvcc->encaps = (enum pppoatm_encaps) be.encaps;
298 pvcc->chan.private = pvcc;
299 pvcc->chan.ops = &pppoatm_ops;
300 pvcc->chan.mtu = atmvcc->qos.txtp.max_sdu - PPP_HDRLEN -
301 (be.encaps == e_vc ? 0 : LLC_LEN);
302 pvcc->wakeup_tasklet = tasklet_proto;
303 pvcc->wakeup_tasklet.data = (unsigned long) &pvcc->chan;
304 if ((err = ppp_register_channel(&pvcc->chan)) != 0) {
305 kfree(pvcc);
306 return err;
307 }
308 atmvcc->user_back = pvcc;
309 atmvcc->push = pppoatm_push;
310 atmvcc->pop = pppoatm_pop;
311 __module_get(THIS_MODULE);
312 return 0;
313}
314
315/*
316 * This handles ioctls actually performed on our vcc - we must return
317 * -ENOIOCTLCMD for any unrecognized ioctl
318 */
319static int pppoatm_ioctl(struct socket *sock, unsigned int cmd,
320 unsigned long arg)
321{
322 struct atm_vcc *atmvcc = ATM_SD(sock);
323 void __user *argp = (void __user *)arg;
324
325 if (cmd != ATM_SETBACKEND && atmvcc->push != pppoatm_push)
326 return -ENOIOCTLCMD;
327 switch (cmd) {
328 case ATM_SETBACKEND: {
329 atm_backend_t b;
330 if (get_user(b, (atm_backend_t __user *) argp))
331 return -EFAULT;
332 if (b != ATM_BACKEND_PPP)
333 return -ENOIOCTLCMD;
334 if (!capable(CAP_NET_ADMIN))
335 return -EPERM;
336 return pppoatm_assign_vcc(atmvcc, argp);
337 }
338 case PPPIOCGCHAN:
339 return put_user(ppp_channel_index(&atmvcc_to_pvcc(atmvcc)->
340 chan), (int __user *) argp) ? -EFAULT : 0;
341 case PPPIOCGUNIT:
342 return put_user(ppp_unit_number(&atmvcc_to_pvcc(atmvcc)->
343 chan), (int __user *) argp) ? -EFAULT : 0;
344 }
345 return -ENOIOCTLCMD;
346}
347
348static struct atm_ioctl pppoatm_ioctl_ops = {
349 .owner = THIS_MODULE,
350 .ioctl = pppoatm_ioctl,
351};
352
353static int __init pppoatm_init(void)
354{
355 register_atm_ioctl(&pppoatm_ioctl_ops);
356 return 0;
357}
358
359static void __exit pppoatm_exit(void)
360{
361 deregister_atm_ioctl(&pppoatm_ioctl_ops);
362}
363
364module_init(pppoatm_init);
365module_exit(pppoatm_exit);
366
367MODULE_AUTHOR("Mitchell Blank Jr <mitch@sfgoth.com>");
368MODULE_DESCRIPTION("RFC2364 PPP over ATM/AAL5");
369MODULE_LICENSE("GPL");
diff --git a/net/atm/proc.c b/net/atm/proc.c
new file mode 100644
index 000000000000..4041054e5282
--- /dev/null
+++ b/net/atm/proc.c
@@ -0,0 +1,514 @@
1/* net/atm/proc.c - ATM /proc interface
2 *
3 * Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA
4 *
5 * seq_file api usage by romieu@fr.zoreil.com
6 *
7 * Evaluating the efficiency of the whole thing if left as an exercise to
8 * the reader.
9 */
10
11#include <linux/config.h>
12#include <linux/module.h> /* for EXPORT_SYMBOL */
13#include <linux/string.h>
14#include <linux/types.h>
15#include <linux/mm.h>
16#include <linux/fs.h>
17#include <linux/stat.h>
18#include <linux/proc_fs.h>
19#include <linux/seq_file.h>
20#include <linux/errno.h>
21#include <linux/atm.h>
22#include <linux/atmdev.h>
23#include <linux/netdevice.h>
24#include <linux/atmclip.h>
25#include <linux/init.h> /* for __init */
26#include <net/atmclip.h>
27#include <asm/uaccess.h>
28#include <asm/atomic.h>
29#include <asm/param.h> /* for HZ */
30#include "resources.h"
31#include "common.h" /* atm_proc_init prototype */
32#include "signaling.h" /* to get sigd - ugly too */
33
34static ssize_t proc_dev_atm_read(struct file *file,char __user *buf,size_t count,
35 loff_t *pos);
36
37static struct file_operations proc_atm_dev_ops = {
38 .owner = THIS_MODULE,
39 .read = proc_dev_atm_read,
40};
41
42static void add_stats(struct seq_file *seq, const char *aal,
43 const struct k_atm_aal_stats *stats)
44{
45 seq_printf(seq, "%s ( %d %d %d %d %d )", aal,
46 atomic_read(&stats->tx),atomic_read(&stats->tx_err),
47 atomic_read(&stats->rx),atomic_read(&stats->rx_err),
48 atomic_read(&stats->rx_drop));
49}
50
51static void atm_dev_info(struct seq_file *seq, const struct atm_dev *dev)
52{
53 int i;
54
55 seq_printf(seq, "%3d %-8s", dev->number, dev->type);
56 for (i = 0; i < ESI_LEN; i++)
57 seq_printf(seq, "%02x", dev->esi[i]);
58 seq_puts(seq, " ");
59 add_stats(seq, "0", &dev->stats.aal0);
60 seq_puts(seq, " ");
61 add_stats(seq, "5", &dev->stats.aal5);
62 seq_printf(seq, "\t[%d]", atomic_read(&dev->refcnt));
63 seq_putc(seq, '\n');
64}
65
66struct vcc_state {
67 int bucket;
68 struct sock *sk;
69 int family;
70};
71
72static inline int compare_family(struct sock *sk, int family)
73{
74 return !family || (sk->sk_family == family);
75}
76
77static int __vcc_walk(struct sock **sock, int family, int *bucket, loff_t l)
78{
79 struct sock *sk = *sock;
80
81 if (sk == (void *)1) {
82 for (*bucket = 0; *bucket < VCC_HTABLE_SIZE; ++*bucket) {
83 struct hlist_head *head = &vcc_hash[*bucket];
84
85 sk = hlist_empty(head) ? NULL : __sk_head(head);
86 if (sk)
87 break;
88 }
89 l--;
90 }
91try_again:
92 for (; sk; sk = sk_next(sk)) {
93 l -= compare_family(sk, family);
94 if (l < 0)
95 goto out;
96 }
97 if (!sk && ++*bucket < VCC_HTABLE_SIZE) {
98 sk = sk_head(&vcc_hash[*bucket]);
99 goto try_again;
100 }
101 sk = (void *)1;
102out:
103 *sock = sk;
104 return (l < 0);
105}
106
107static inline void *vcc_walk(struct vcc_state *state, loff_t l)
108{
109 return __vcc_walk(&state->sk, state->family, &state->bucket, l) ?
110 state : NULL;
111}
112
113static int __vcc_seq_open(struct inode *inode, struct file *file,
114 int family, struct seq_operations *ops)
115{
116 struct vcc_state *state;
117 struct seq_file *seq;
118 int rc = -ENOMEM;
119
120 state = kmalloc(sizeof(*state), GFP_KERNEL);
121 if (!state)
122 goto out;
123
124 rc = seq_open(file, ops);
125 if (rc)
126 goto out_kfree;
127
128 state->family = family;
129
130 seq = file->private_data;
131 seq->private = state;
132out:
133 return rc;
134out_kfree:
135 kfree(state);
136 goto out;
137}
138
139static int vcc_seq_release(struct inode *inode, struct file *file)
140{
141 return seq_release_private(inode, file);
142}
143
144static void *vcc_seq_start(struct seq_file *seq, loff_t *pos)
145{
146 struct vcc_state *state = seq->private;
147 loff_t left = *pos;
148
149 read_lock(&vcc_sklist_lock);
150 state->sk = (void *)1;
151 return left ? vcc_walk(state, left) : (void *)1;
152}
153
154static void vcc_seq_stop(struct seq_file *seq, void *v)
155{
156 read_unlock(&vcc_sklist_lock);
157}
158
159static void *vcc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
160{
161 struct vcc_state *state = seq->private;
162
163 v = vcc_walk(state, 1);
164 *pos += !!PTR_ERR(v);
165 return v;
166}
167
168static void pvc_info(struct seq_file *seq, struct atm_vcc *vcc)
169{
170 static const char *class_name[] = { "off","UBR","CBR","VBR","ABR" };
171 static const char *aal_name[] = {
172 "---", "1", "2", "3/4", /* 0- 3 */
173 "???", "5", "???", "???", /* 4- 7 */
174 "???", "???", "???", "???", /* 8-11 */
175 "???", "0", "???", "???"}; /* 12-15 */
176
177 seq_printf(seq, "%3d %3d %5d %-3s %7d %-5s %7d %-6s",
178 vcc->dev->number,vcc->vpi,vcc->vci,
179 vcc->qos.aal >= sizeof(aal_name)/sizeof(aal_name[0]) ? "err" :
180 aal_name[vcc->qos.aal],vcc->qos.rxtp.min_pcr,
181 class_name[vcc->qos.rxtp.traffic_class],vcc->qos.txtp.min_pcr,
182 class_name[vcc->qos.txtp.traffic_class]);
183 if (test_bit(ATM_VF_IS_CLIP, &vcc->flags)) {
184 struct clip_vcc *clip_vcc = CLIP_VCC(vcc);
185 struct net_device *dev;
186
187 dev = clip_vcc->entry ? clip_vcc->entry->neigh->dev : NULL;
188 seq_printf(seq, "CLIP, Itf:%s, Encap:",
189 dev ? dev->name : "none?");
190 seq_printf(seq, "%s", clip_vcc->encap ? "LLC/SNAP" : "None");
191 }
192 seq_putc(seq, '\n');
193}
194
195static const char *vcc_state(struct atm_vcc *vcc)
196{
197 static const char *map[] = { ATM_VS2TXT_MAP };
198
199 return map[ATM_VF2VS(vcc->flags)];
200}
201
202static void vcc_info(struct seq_file *seq, struct atm_vcc *vcc)
203{
204 struct sock *sk = sk_atm(vcc);
205
206 seq_printf(seq, "%p ", vcc);
207 if (!vcc->dev)
208 seq_printf(seq, "Unassigned ");
209 else
210 seq_printf(seq, "%3d %3d %5d ", vcc->dev->number, vcc->vpi,
211 vcc->vci);
212 switch (sk->sk_family) {
213 case AF_ATMPVC:
214 seq_printf(seq, "PVC");
215 break;
216 case AF_ATMSVC:
217 seq_printf(seq, "SVC");
218 break;
219 default:
220 seq_printf(seq, "%3d", sk->sk_family);
221 }
222 seq_printf(seq, " %04lx %5d %7d/%7d %7d/%7d [%d]\n", vcc->flags, sk->sk_err,
223 atomic_read(&sk->sk_wmem_alloc), sk->sk_sndbuf,
224 atomic_read(&sk->sk_rmem_alloc), sk->sk_rcvbuf,
225 atomic_read(&sk->sk_refcnt));
226}
227
228static void svc_info(struct seq_file *seq, struct atm_vcc *vcc)
229{
230 if (!vcc->dev)
231 seq_printf(seq, sizeof(void *) == 4 ?
232 "N/A@%p%10s" : "N/A@%p%2s", vcc, "");
233 else
234 seq_printf(seq, "%3d %3d %5d ",
235 vcc->dev->number, vcc->vpi, vcc->vci);
236 seq_printf(seq, "%-10s ", vcc_state(vcc));
237 seq_printf(seq, "%s%s", vcc->remote.sas_addr.pub,
238 *vcc->remote.sas_addr.pub && *vcc->remote.sas_addr.prv ? "+" : "");
239 if (*vcc->remote.sas_addr.prv) {
240 int i;
241
242 for (i = 0; i < ATM_ESA_LEN; i++)
243 seq_printf(seq, "%02x", vcc->remote.sas_addr.prv[i]);
244 }
245 seq_putc(seq, '\n');
246}
247
248static int atm_dev_seq_show(struct seq_file *seq, void *v)
249{
250 static char atm_dev_banner[] =
251 "Itf Type ESI/\"MAC\"addr "
252 "AAL(TX,err,RX,err,drop) ... [refcnt]\n";
253
254 if (v == (void *)1)
255 seq_puts(seq, atm_dev_banner);
256 else {
257 struct atm_dev *dev = list_entry(v, struct atm_dev, dev_list);
258
259 atm_dev_info(seq, dev);
260 }
261 return 0;
262}
263
264static struct seq_operations atm_dev_seq_ops = {
265 .start = atm_dev_seq_start,
266 .next = atm_dev_seq_next,
267 .stop = atm_dev_seq_stop,
268 .show = atm_dev_seq_show,
269};
270
271static int atm_dev_seq_open(struct inode *inode, struct file *file)
272{
273 return seq_open(file, &atm_dev_seq_ops);
274}
275
276static struct file_operations devices_seq_fops = {
277 .open = atm_dev_seq_open,
278 .read = seq_read,
279 .llseek = seq_lseek,
280 .release = seq_release,
281};
282
283static int pvc_seq_show(struct seq_file *seq, void *v)
284{
285 static char atm_pvc_banner[] =
286 "Itf VPI VCI AAL RX(PCR,Class) TX(PCR,Class)\n";
287
288 if (v == (void *)1)
289 seq_puts(seq, atm_pvc_banner);
290 else {
291 struct vcc_state *state = seq->private;
292 struct atm_vcc *vcc = atm_sk(state->sk);
293
294 pvc_info(seq, vcc);
295 }
296 return 0;
297}
298
299static struct seq_operations pvc_seq_ops = {
300 .start = vcc_seq_start,
301 .next = vcc_seq_next,
302 .stop = vcc_seq_stop,
303 .show = pvc_seq_show,
304};
305
306static int pvc_seq_open(struct inode *inode, struct file *file)
307{
308 return __vcc_seq_open(inode, file, PF_ATMPVC, &pvc_seq_ops);
309}
310
311static struct file_operations pvc_seq_fops = {
312 .open = pvc_seq_open,
313 .read = seq_read,
314 .llseek = seq_lseek,
315 .release = vcc_seq_release,
316};
317
318static int vcc_seq_show(struct seq_file *seq, void *v)
319{
320 if (v == (void *)1) {
321 seq_printf(seq, sizeof(void *) == 4 ? "%-8s%s" : "%-16s%s",
322 "Address ", "Itf VPI VCI Fam Flags Reply "
323 "Send buffer Recv buffer [refcnt]\n");
324 } else {
325 struct vcc_state *state = seq->private;
326 struct atm_vcc *vcc = atm_sk(state->sk);
327
328 vcc_info(seq, vcc);
329 }
330 return 0;
331}
332
333static struct seq_operations vcc_seq_ops = {
334 .start = vcc_seq_start,
335 .next = vcc_seq_next,
336 .stop = vcc_seq_stop,
337 .show = vcc_seq_show,
338};
339
340static int vcc_seq_open(struct inode *inode, struct file *file)
341{
342 return __vcc_seq_open(inode, file, 0, &vcc_seq_ops);
343}
344
345static struct file_operations vcc_seq_fops = {
346 .open = vcc_seq_open,
347 .read = seq_read,
348 .llseek = seq_lseek,
349 .release = vcc_seq_release,
350};
351
352static int svc_seq_show(struct seq_file *seq, void *v)
353{
354 static char atm_svc_banner[] =
355 "Itf VPI VCI State Remote\n";
356
357 if (v == (void *)1)
358 seq_puts(seq, atm_svc_banner);
359 else {
360 struct vcc_state *state = seq->private;
361 struct atm_vcc *vcc = atm_sk(state->sk);
362
363 svc_info(seq, vcc);
364 }
365 return 0;
366}
367
368static struct seq_operations svc_seq_ops = {
369 .start = vcc_seq_start,
370 .next = vcc_seq_next,
371 .stop = vcc_seq_stop,
372 .show = svc_seq_show,
373};
374
375static int svc_seq_open(struct inode *inode, struct file *file)
376{
377 return __vcc_seq_open(inode, file, PF_ATMSVC, &svc_seq_ops);
378}
379
380static struct file_operations svc_seq_fops = {
381 .open = svc_seq_open,
382 .read = seq_read,
383 .llseek = seq_lseek,
384 .release = vcc_seq_release,
385};
386
387static ssize_t proc_dev_atm_read(struct file *file, char __user *buf,
388 size_t count, loff_t *pos)
389{
390 struct atm_dev *dev;
391 unsigned long page;
392 int length;
393
394 if (count == 0) return 0;
395 page = get_zeroed_page(GFP_KERNEL);
396 if (!page) return -ENOMEM;
397 dev = PDE(file->f_dentry->d_inode)->data;
398 if (!dev->ops->proc_read)
399 length = -EINVAL;
400 else {
401 length = dev->ops->proc_read(dev,pos,(char *) page);
402 if (length > count) length = -EINVAL;
403 }
404 if (length >= 0) {
405 if (copy_to_user(buf,(char *) page,length)) length = -EFAULT;
406 (*pos)++;
407 }
408 free_page(page);
409 return length;
410}
411
412
413struct proc_dir_entry *atm_proc_root;
414EXPORT_SYMBOL(atm_proc_root);
415
416
417int atm_proc_dev_register(struct atm_dev *dev)
418{
419 int digits,num;
420 int error;
421
422 /* No proc info */
423 if (!dev->ops->proc_read)
424 return 0;
425
426 error = -ENOMEM;
427 digits = 0;
428 for (num = dev->number; num; num /= 10) digits++;
429 if (!digits) digits++;
430
431 dev->proc_name = kmalloc(strlen(dev->type) + digits + 2, GFP_KERNEL);
432 if (!dev->proc_name)
433 goto err_out;
434 sprintf(dev->proc_name,"%s:%d",dev->type, dev->number);
435
436 dev->proc_entry = create_proc_entry(dev->proc_name, 0, atm_proc_root);
437 if (!dev->proc_entry)
438 goto err_free_name;
439 dev->proc_entry->data = dev;
440 dev->proc_entry->proc_fops = &proc_atm_dev_ops;
441 dev->proc_entry->owner = THIS_MODULE;
442 return 0;
443err_free_name:
444 kfree(dev->proc_name);
445err_out:
446 return error;
447}
448
449
450void atm_proc_dev_deregister(struct atm_dev *dev)
451{
452 if (!dev->ops->proc_read)
453 return;
454
455 remove_proc_entry(dev->proc_name, atm_proc_root);
456 kfree(dev->proc_name);
457}
458
459static struct atm_proc_entry {
460 char *name;
461 struct file_operations *proc_fops;
462 struct proc_dir_entry *dirent;
463} atm_proc_ents[] = {
464 { .name = "devices", .proc_fops = &devices_seq_fops },
465 { .name = "pvc", .proc_fops = &pvc_seq_fops },
466 { .name = "svc", .proc_fops = &svc_seq_fops },
467 { .name = "vc", .proc_fops = &vcc_seq_fops },
468 { .name = NULL, .proc_fops = NULL }
469};
470
471static void atm_proc_dirs_remove(void)
472{
473 static struct atm_proc_entry *e;
474
475 for (e = atm_proc_ents; e->name; e++) {
476 if (e->dirent)
477 remove_proc_entry(e->name, atm_proc_root);
478 }
479 remove_proc_entry("net/atm", NULL);
480}
481
482int __init atm_proc_init(void)
483{
484 static struct atm_proc_entry *e;
485 int ret;
486
487 atm_proc_root = proc_mkdir("net/atm",NULL);
488 if (!atm_proc_root)
489 goto err_out;
490 for (e = atm_proc_ents; e->name; e++) {
491 struct proc_dir_entry *dirent;
492
493 dirent = create_proc_entry(e->name, S_IRUGO, atm_proc_root);
494 if (!dirent)
495 goto err_out_remove;
496 dirent->proc_fops = e->proc_fops;
497 dirent->owner = THIS_MODULE;
498 e->dirent = dirent;
499 }
500 ret = 0;
501out:
502 return ret;
503
504err_out_remove:
505 atm_proc_dirs_remove();
506err_out:
507 ret = -ENOMEM;
508 goto out;
509}
510
511void __exit atm_proc_exit(void)
512{
513 atm_proc_dirs_remove();
514}
diff --git a/net/atm/protocols.h b/net/atm/protocols.h
new file mode 100644
index 000000000000..acdfc856222d
--- /dev/null
+++ b/net/atm/protocols.h
@@ -0,0 +1,13 @@
1/* net/atm/protocols.h - ATM protocol handler entry points */
2
3/* Written 1995-1997 by Werner Almesberger, EPFL LRC */
4
5
6#ifndef NET_ATM_PROTOCOLS_H
7#define NET_ATM_PROTOCOLS_H
8
9int atm_init_aal0(struct atm_vcc *vcc); /* "raw" AAL0 */
10int atm_init_aal34(struct atm_vcc *vcc);/* "raw" AAL3/4 transport */
11int atm_init_aal5(struct atm_vcc *vcc); /* "raw" AAL5 transport */
12
13#endif
diff --git a/net/atm/pvc.c b/net/atm/pvc.c
new file mode 100644
index 000000000000..2684a92da22b
--- /dev/null
+++ b/net/atm/pvc.c
@@ -0,0 +1,155 @@
1/* net/atm/pvc.c - ATM PVC sockets */
2
3/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
4
5
6#include <linux/config.h>
7#include <linux/net.h> /* struct socket, struct proto_ops */
8#include <linux/atm.h> /* ATM stuff */
9#include <linux/atmdev.h> /* ATM devices */
10#include <linux/errno.h> /* error codes */
11#include <linux/kernel.h> /* printk */
12#include <linux/init.h>
13#include <linux/skbuff.h>
14#include <linux/bitops.h>
15#include <net/sock.h> /* for sock_no_* */
16
17#include "resources.h" /* devs and vccs */
18#include "common.h" /* common for PVCs and SVCs */
19
20
21static int pvc_shutdown(struct socket *sock,int how)
22{
23 return 0;
24}
25
26
27static int pvc_bind(struct socket *sock,struct sockaddr *sockaddr,
28 int sockaddr_len)
29{
30 struct sock *sk = sock->sk;
31 struct sockaddr_atmpvc *addr;
32 struct atm_vcc *vcc;
33 int error;
34
35 if (sockaddr_len != sizeof(struct sockaddr_atmpvc)) return -EINVAL;
36 addr = (struct sockaddr_atmpvc *) sockaddr;
37 if (addr->sap_family != AF_ATMPVC) return -EAFNOSUPPORT;
38 lock_sock(sk);
39 vcc = ATM_SD(sock);
40 if (!test_bit(ATM_VF_HASQOS, &vcc->flags)) {
41 error = -EBADFD;
42 goto out;
43 }
44 if (test_bit(ATM_VF_PARTIAL,&vcc->flags)) {
45 if (vcc->vpi != ATM_VPI_UNSPEC) addr->sap_addr.vpi = vcc->vpi;
46 if (vcc->vci != ATM_VCI_UNSPEC) addr->sap_addr.vci = vcc->vci;
47 }
48 error = vcc_connect(sock, addr->sap_addr.itf, addr->sap_addr.vpi,
49 addr->sap_addr.vci);
50out:
51 release_sock(sk);
52 return error;
53}
54
55
56static int pvc_connect(struct socket *sock,struct sockaddr *sockaddr,
57 int sockaddr_len,int flags)
58{
59 return pvc_bind(sock,sockaddr,sockaddr_len);
60}
61
62static int pvc_setsockopt(struct socket *sock, int level, int optname,
63 char __user *optval, int optlen)
64{
65 struct sock *sk = sock->sk;
66 int error;
67
68 lock_sock(sk);
69 error = vcc_setsockopt(sock, level, optname, optval, optlen);
70 release_sock(sk);
71 return error;
72}
73
74
75static int pvc_getsockopt(struct socket *sock, int level, int optname,
76 char __user *optval, int __user *optlen)
77{
78 struct sock *sk = sock->sk;
79 int error;
80
81 lock_sock(sk);
82 error = vcc_getsockopt(sock, level, optname, optval, optlen);
83 release_sock(sk);
84 return error;
85}
86
87
88static int pvc_getname(struct socket *sock,struct sockaddr *sockaddr,
89 int *sockaddr_len,int peer)
90{
91 struct sockaddr_atmpvc *addr;
92 struct atm_vcc *vcc = ATM_SD(sock);
93
94 if (!vcc->dev || !test_bit(ATM_VF_ADDR,&vcc->flags)) return -ENOTCONN;
95 *sockaddr_len = sizeof(struct sockaddr_atmpvc);
96 addr = (struct sockaddr_atmpvc *) sockaddr;
97 addr->sap_family = AF_ATMPVC;
98 addr->sap_addr.itf = vcc->dev->number;
99 addr->sap_addr.vpi = vcc->vpi;
100 addr->sap_addr.vci = vcc->vci;
101 return 0;
102}
103
104
105static struct proto_ops pvc_proto_ops = {
106 .family = PF_ATMPVC,
107 .owner = THIS_MODULE,
108
109 .release = vcc_release,
110 .bind = pvc_bind,
111 .connect = pvc_connect,
112 .socketpair = sock_no_socketpair,
113 .accept = sock_no_accept,
114 .getname = pvc_getname,
115 .poll = vcc_poll,
116 .ioctl = vcc_ioctl,
117 .listen = sock_no_listen,
118 .shutdown = pvc_shutdown,
119 .setsockopt = pvc_setsockopt,
120 .getsockopt = pvc_getsockopt,
121 .sendmsg = vcc_sendmsg,
122 .recvmsg = vcc_recvmsg,
123 .mmap = sock_no_mmap,
124 .sendpage = sock_no_sendpage,
125};
126
127
128static int pvc_create(struct socket *sock,int protocol)
129{
130 sock->ops = &pvc_proto_ops;
131 return vcc_create(sock, protocol, PF_ATMPVC);
132}
133
134
135static struct net_proto_family pvc_family_ops = {
136 .family = PF_ATMPVC,
137 .create = pvc_create,
138 .owner = THIS_MODULE,
139};
140
141
142/*
143 * Initialize the ATM PVC protocol family
144 */
145
146
147int __init atmpvc_init(void)
148{
149 return sock_register(&pvc_family_ops);
150}
151
152void atmpvc_exit(void)
153{
154 sock_unregister(PF_ATMPVC);
155}
diff --git a/net/atm/raw.c b/net/atm/raw.c
new file mode 100644
index 000000000000..4a0466e91aa6
--- /dev/null
+++ b/net/atm/raw.c
@@ -0,0 +1,98 @@
1/* net/atm/raw.c - Raw AAL0 and AAL5 transports */
2
3/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
4
5
6#include <linux/module.h>
7#include <linux/sched.h>
8#include <linux/atmdev.h>
9#include <linux/kernel.h>
10#include <linux/skbuff.h>
11#include <linux/mm.h>
12
13#include "common.h"
14#include "protocols.h"
15
16
17#if 0
18#define DPRINTK(format,args...) printk(KERN_DEBUG format,##args)
19#else
20#define DPRINTK(format,args...)
21#endif
22
23
24/*
25 * SKB == NULL indicates that the link is being closed
26 */
27
28static void atm_push_raw(struct atm_vcc *vcc,struct sk_buff *skb)
29{
30 if (skb) {
31 struct sock *sk = sk_atm(vcc);
32
33 skb_queue_tail(&sk->sk_receive_queue, skb);
34 sk->sk_data_ready(sk, skb->len);
35 }
36}
37
38
39static void atm_pop_raw(struct atm_vcc *vcc,struct sk_buff *skb)
40{
41 struct sock *sk = sk_atm(vcc);
42
43 DPRINTK("APopR (%d) %d -= %d\n", vcc->vci, sk->sk_wmem_alloc,
44 skb->truesize);
45 atomic_sub(skb->truesize, &sk->sk_wmem_alloc);
46 dev_kfree_skb_any(skb);
47 sk->sk_write_space(sk);
48}
49
50
51static int atm_send_aal0(struct atm_vcc *vcc,struct sk_buff *skb)
52{
53 /*
54 * Note that if vpi/vci are _ANY or _UNSPEC the below will
55 * still work
56 */
57 if (!capable(CAP_NET_ADMIN) &&
58 (((u32 *) skb->data)[0] & (ATM_HDR_VPI_MASK | ATM_HDR_VCI_MASK)) !=
59 ((vcc->vpi << ATM_HDR_VPI_SHIFT) | (vcc->vci << ATM_HDR_VCI_SHIFT)))
60 {
61 kfree_skb(skb);
62 return -EADDRNOTAVAIL;
63 }
64 return vcc->dev->ops->send(vcc,skb);
65}
66
67
68int atm_init_aal0(struct atm_vcc *vcc)
69{
70 vcc->push = atm_push_raw;
71 vcc->pop = atm_pop_raw;
72 vcc->push_oam = NULL;
73 vcc->send = atm_send_aal0;
74 return 0;
75}
76
77
78int atm_init_aal34(struct atm_vcc *vcc)
79{
80 vcc->push = atm_push_raw;
81 vcc->pop = atm_pop_raw;
82 vcc->push_oam = NULL;
83 vcc->send = vcc->dev->ops->send;
84 return 0;
85}
86
87
88int atm_init_aal5(struct atm_vcc *vcc)
89{
90 vcc->push = atm_push_raw;
91 vcc->pop = atm_pop_raw;
92 vcc->push_oam = NULL;
93 vcc->send = vcc->dev->ops->send;
94 return 0;
95}
96
97
98EXPORT_SYMBOL(atm_init_aal5);
diff --git a/net/atm/resources.c b/net/atm/resources.c
new file mode 100644
index 000000000000..33f1685dbb77
--- /dev/null
+++ b/net/atm/resources.c
@@ -0,0 +1,432 @@
1/* net/atm/resources.c - Statically allocated resources */
2
3/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
4
5/* Fixes
6 * Arnaldo Carvalho de Melo <acme@conectiva.com.br>
7 * 2002/01 - don't free the whole struct sock on sk->destruct time,
8 * use the default destruct function initialized by sock_init_data */
9
10
11#include <linux/config.h>
12#include <linux/ctype.h>
13#include <linux/string.h>
14#include <linux/atmdev.h>
15#include <linux/sonet.h>
16#include <linux/kernel.h> /* for barrier */
17#include <linux/module.h>
18#include <linux/bitops.h>
19#include <linux/delay.h>
20#include <net/sock.h> /* for struct sock */
21
22#include "common.h"
23#include "resources.h"
24#include "addr.h"
25
26
27LIST_HEAD(atm_devs);
28DEFINE_SPINLOCK(atm_dev_lock);
29
30static struct atm_dev *__alloc_atm_dev(const char *type)
31{
32 struct atm_dev *dev;
33
34 dev = kmalloc(sizeof(*dev), GFP_KERNEL);
35 if (!dev)
36 return NULL;
37 memset(dev, 0, sizeof(*dev));
38 dev->type = type;
39 dev->signal = ATM_PHY_SIG_UNKNOWN;
40 dev->link_rate = ATM_OC3_PCR;
41 spin_lock_init(&dev->lock);
42 INIT_LIST_HEAD(&dev->local);
43
44 return dev;
45}
46
47static void __free_atm_dev(struct atm_dev *dev)
48{
49 kfree(dev);
50}
51
52static struct atm_dev *__atm_dev_lookup(int number)
53{
54 struct atm_dev *dev;
55 struct list_head *p;
56
57 list_for_each(p, &atm_devs) {
58 dev = list_entry(p, struct atm_dev, dev_list);
59 if ((dev->ops) && (dev->number == number)) {
60 atm_dev_hold(dev);
61 return dev;
62 }
63 }
64 return NULL;
65}
66
67struct atm_dev *atm_dev_lookup(int number)
68{
69 struct atm_dev *dev;
70
71 spin_lock(&atm_dev_lock);
72 dev = __atm_dev_lookup(number);
73 spin_unlock(&atm_dev_lock);
74 return dev;
75}
76
77struct atm_dev *atm_dev_register(const char *type, const struct atmdev_ops *ops,
78 int number, unsigned long *flags)
79{
80 struct atm_dev *dev, *inuse;
81
82 dev = __alloc_atm_dev(type);
83 if (!dev) {
84 printk(KERN_ERR "atm_dev_register: no space for dev %s\n",
85 type);
86 return NULL;
87 }
88 spin_lock(&atm_dev_lock);
89 if (number != -1) {
90 if ((inuse = __atm_dev_lookup(number))) {
91 atm_dev_put(inuse);
92 spin_unlock(&atm_dev_lock);
93 __free_atm_dev(dev);
94 return NULL;
95 }
96 dev->number = number;
97 } else {
98 dev->number = 0;
99 while ((inuse = __atm_dev_lookup(dev->number))) {
100 atm_dev_put(inuse);
101 dev->number++;
102 }
103 }
104
105 dev->ops = ops;
106 if (flags)
107 dev->flags = *flags;
108 else
109 memset(&dev->flags, 0, sizeof(dev->flags));
110 memset(&dev->stats, 0, sizeof(dev->stats));
111 atomic_set(&dev->refcnt, 1);
112 list_add_tail(&dev->dev_list, &atm_devs);
113 spin_unlock(&atm_dev_lock);
114
115 if (atm_proc_dev_register(dev) < 0) {
116 printk(KERN_ERR "atm_dev_register: "
117 "atm_proc_dev_register failed for dev %s\n",
118 type);
119 spin_lock(&atm_dev_lock);
120 list_del(&dev->dev_list);
121 spin_unlock(&atm_dev_lock);
122 __free_atm_dev(dev);
123 return NULL;
124 }
125
126 return dev;
127}
128
129
130void atm_dev_deregister(struct atm_dev *dev)
131{
132 unsigned long warning_time;
133
134 atm_proc_dev_deregister(dev);
135
136 spin_lock(&atm_dev_lock);
137 list_del(&dev->dev_list);
138 spin_unlock(&atm_dev_lock);
139
140 warning_time = jiffies;
141 while (atomic_read(&dev->refcnt) != 1) {
142 msleep(250);
143 if ((jiffies - warning_time) > 10 * HZ) {
144 printk(KERN_EMERG "atm_dev_deregister: waiting for "
145 "dev %d to become free. Usage count = %d\n",
146 dev->number, atomic_read(&dev->refcnt));
147 warning_time = jiffies;
148 }
149 }
150
151 __free_atm_dev(dev);
152}
153
154void shutdown_atm_dev(struct atm_dev *dev)
155{
156 if (atomic_read(&dev->refcnt) > 1) {
157 set_bit(ATM_DF_CLOSE, &dev->flags);
158 return;
159 }
160 if (dev->ops->dev_close)
161 dev->ops->dev_close(dev);
162 atm_dev_deregister(dev);
163}
164
165
166static void copy_aal_stats(struct k_atm_aal_stats *from,
167 struct atm_aal_stats *to)
168{
169#define __HANDLE_ITEM(i) to->i = atomic_read(&from->i)
170 __AAL_STAT_ITEMS
171#undef __HANDLE_ITEM
172}
173
174
175static void subtract_aal_stats(struct k_atm_aal_stats *from,
176 struct atm_aal_stats *to)
177{
178#define __HANDLE_ITEM(i) atomic_sub(to->i, &from->i)
179 __AAL_STAT_ITEMS
180#undef __HANDLE_ITEM
181}
182
183
184static int fetch_stats(struct atm_dev *dev, struct atm_dev_stats __user *arg, int zero)
185{
186 struct atm_dev_stats tmp;
187 int error = 0;
188
189 copy_aal_stats(&dev->stats.aal0, &tmp.aal0);
190 copy_aal_stats(&dev->stats.aal34, &tmp.aal34);
191 copy_aal_stats(&dev->stats.aal5, &tmp.aal5);
192 if (arg)
193 error = copy_to_user(arg, &tmp, sizeof(tmp));
194 if (zero && !error) {
195 subtract_aal_stats(&dev->stats.aal0, &tmp.aal0);
196 subtract_aal_stats(&dev->stats.aal34, &tmp.aal34);
197 subtract_aal_stats(&dev->stats.aal5, &tmp.aal5);
198 }
199 return error ? -EFAULT : 0;
200}
201
202
203int atm_dev_ioctl(unsigned int cmd, void __user *arg)
204{
205 void __user *buf;
206 int error, len, number, size = 0;
207 struct atm_dev *dev;
208 struct list_head *p;
209 int *tmp_buf, *tmp_p;
210 struct atm_iobuf __user *iobuf = arg;
211 struct atmif_sioc __user *sioc = arg;
212 switch (cmd) {
213 case ATM_GETNAMES:
214 if (get_user(buf, &iobuf->buffer))
215 return -EFAULT;
216 if (get_user(len, &iobuf->length))
217 return -EFAULT;
218 spin_lock(&atm_dev_lock);
219 list_for_each(p, &atm_devs)
220 size += sizeof(int);
221 if (size > len) {
222 spin_unlock(&atm_dev_lock);
223 return -E2BIG;
224 }
225 tmp_buf = kmalloc(size, GFP_ATOMIC);
226 if (!tmp_buf) {
227 spin_unlock(&atm_dev_lock);
228 return -ENOMEM;
229 }
230 tmp_p = tmp_buf;
231 list_for_each(p, &atm_devs) {
232 dev = list_entry(p, struct atm_dev, dev_list);
233 *tmp_p++ = dev->number;
234 }
235 spin_unlock(&atm_dev_lock);
236 error = ((copy_to_user(buf, tmp_buf, size)) ||
237 put_user(size, &iobuf->length))
238 ? -EFAULT : 0;
239 kfree(tmp_buf);
240 return error;
241 default:
242 break;
243 }
244
245 if (get_user(buf, &sioc->arg))
246 return -EFAULT;
247 if (get_user(len, &sioc->length))
248 return -EFAULT;
249 if (get_user(number, &sioc->number))
250 return -EFAULT;
251
252 if (!(dev = atm_dev_lookup(number)))
253 return -ENODEV;
254
255 switch (cmd) {
256 case ATM_GETTYPE:
257 size = strlen(dev->type) + 1;
258 if (copy_to_user(buf, dev->type, size)) {
259 error = -EFAULT;
260 goto done;
261 }
262 break;
263 case ATM_GETESI:
264 size = ESI_LEN;
265 if (copy_to_user(buf, dev->esi, size)) {
266 error = -EFAULT;
267 goto done;
268 }
269 break;
270 case ATM_SETESI:
271 {
272 int i;
273
274 for (i = 0; i < ESI_LEN; i++)
275 if (dev->esi[i]) {
276 error = -EEXIST;
277 goto done;
278 }
279 }
280 /* fall through */
281 case ATM_SETESIF:
282 {
283 unsigned char esi[ESI_LEN];
284
285 if (!capable(CAP_NET_ADMIN)) {
286 error = -EPERM;
287 goto done;
288 }
289 if (copy_from_user(esi, buf, ESI_LEN)) {
290 error = -EFAULT;
291 goto done;
292 }
293 memcpy(dev->esi, esi, ESI_LEN);
294 error = ESI_LEN;
295 goto done;
296 }
297 case ATM_GETSTATZ:
298 if (!capable(CAP_NET_ADMIN)) {
299 error = -EPERM;
300 goto done;
301 }
302 /* fall through */
303 case ATM_GETSTAT:
304 size = sizeof(struct atm_dev_stats);
305 error = fetch_stats(dev, buf, cmd == ATM_GETSTATZ);
306 if (error)
307 goto done;
308 break;
309 case ATM_GETCIRANGE:
310 size = sizeof(struct atm_cirange);
311 if (copy_to_user(buf, &dev->ci_range, size)) {
312 error = -EFAULT;
313 goto done;
314 }
315 break;
316 case ATM_GETLINKRATE:
317 size = sizeof(int);
318 if (copy_to_user(buf, &dev->link_rate, size)) {
319 error = -EFAULT;
320 goto done;
321 }
322 break;
323 case ATM_RSTADDR:
324 if (!capable(CAP_NET_ADMIN)) {
325 error = -EPERM;
326 goto done;
327 }
328 atm_reset_addr(dev);
329 break;
330 case ATM_ADDADDR:
331 case ATM_DELADDR:
332 if (!capable(CAP_NET_ADMIN)) {
333 error = -EPERM;
334 goto done;
335 }
336 {
337 struct sockaddr_atmsvc addr;
338
339 if (copy_from_user(&addr, buf, sizeof(addr))) {
340 error = -EFAULT;
341 goto done;
342 }
343 if (cmd == ATM_ADDADDR)
344 error = atm_add_addr(dev, &addr);
345 else
346 error = atm_del_addr(dev, &addr);
347 goto done;
348 }
349 case ATM_GETADDR:
350 error = atm_get_addr(dev, buf, len);
351 if (error < 0)
352 goto done;
353 size = error;
354 /* may return 0, but later on size == 0 means "don't
355 write the length" */
356 error = put_user(size, &sioc->length)
357 ? -EFAULT : 0;
358 goto done;
359 case ATM_SETLOOP:
360 if (__ATM_LM_XTRMT((int) (unsigned long) buf) &&
361 __ATM_LM_XTLOC((int) (unsigned long) buf) >
362 __ATM_LM_XTRMT((int) (unsigned long) buf)) {
363 error = -EINVAL;
364 goto done;
365 }
366 /* fall through */
367 case ATM_SETCIRANGE:
368 case SONET_GETSTATZ:
369 case SONET_SETDIAG:
370 case SONET_CLRDIAG:
371 case SONET_SETFRAMING:
372 if (!capable(CAP_NET_ADMIN)) {
373 error = -EPERM;
374 goto done;
375 }
376 /* fall through */
377 default:
378 if (!dev->ops->ioctl) {
379 error = -EINVAL;
380 goto done;
381 }
382 size = dev->ops->ioctl(dev, cmd, buf);
383 if (size < 0) {
384 error = (size == -ENOIOCTLCMD ? -EINVAL : size);
385 goto done;
386 }
387 }
388
389 if (size)
390 error = put_user(size, &sioc->length)
391 ? -EFAULT : 0;
392 else
393 error = 0;
394done:
395 atm_dev_put(dev);
396 return error;
397}
398
399static __inline__ void *dev_get_idx(loff_t left)
400{
401 struct list_head *p;
402
403 list_for_each(p, &atm_devs) {
404 if (!--left)
405 break;
406 }
407 return (p != &atm_devs) ? p : NULL;
408}
409
410void *atm_dev_seq_start(struct seq_file *seq, loff_t *pos)
411{
412 spin_lock(&atm_dev_lock);
413 return *pos ? dev_get_idx(*pos) : (void *) 1;
414}
415
416void atm_dev_seq_stop(struct seq_file *seq, void *v)
417{
418 spin_unlock(&atm_dev_lock);
419}
420
421void *atm_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos)
422{
423 ++*pos;
424 v = (v == (void *)1) ? atm_devs.next : ((struct list_head *)v)->next;
425 return (v == &atm_devs) ? NULL : v;
426}
427
428
429EXPORT_SYMBOL(atm_dev_register);
430EXPORT_SYMBOL(atm_dev_deregister);
431EXPORT_SYMBOL(atm_dev_lookup);
432EXPORT_SYMBOL(shutdown_atm_dev);
diff --git a/net/atm/resources.h b/net/atm/resources.h
new file mode 100644
index 000000000000..12910619dbb6
--- /dev/null
+++ b/net/atm/resources.h
@@ -0,0 +1,46 @@
1/* net/atm/resources.h - ATM-related resources */
2
3/* Written 1995-1998 by Werner Almesberger, EPFL LRC/ICA */
4
5
6#ifndef NET_ATM_RESOURCES_H
7#define NET_ATM_RESOURCES_H
8
9#include <linux/config.h>
10#include <linux/atmdev.h>
11
12
13extern struct list_head atm_devs;
14extern spinlock_t atm_dev_lock;
15
16
17int atm_dev_ioctl(unsigned int cmd, void __user *arg);
18
19
20#ifdef CONFIG_PROC_FS
21
22#include <linux/proc_fs.h>
23
24void *atm_dev_seq_start(struct seq_file *seq, loff_t *pos);
25void atm_dev_seq_stop(struct seq_file *seq, void *v);
26void *atm_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos);
27
28
29int atm_proc_dev_register(struct atm_dev *dev);
30void atm_proc_dev_deregister(struct atm_dev *dev);
31
32#else
33
34static inline int atm_proc_dev_register(struct atm_dev *dev)
35{
36 return 0;
37}
38
39static inline void atm_proc_dev_deregister(struct atm_dev *dev)
40{
41 /* nothing */
42}
43
44#endif /* CONFIG_PROC_FS */
45
46#endif
diff --git a/net/atm/signaling.c b/net/atm/signaling.c
new file mode 100644
index 000000000000..6ff803154c04
--- /dev/null
+++ b/net/atm/signaling.c
@@ -0,0 +1,280 @@
1/* net/atm/signaling.c - ATM signaling */
2
3/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
4
5
6#include <linux/errno.h> /* error codes */
7#include <linux/kernel.h> /* printk */
8#include <linux/skbuff.h>
9#include <linux/wait.h>
10#include <linux/sched.h> /* jiffies and HZ */
11#include <linux/atm.h> /* ATM stuff */
12#include <linux/atmsap.h>
13#include <linux/atmsvc.h>
14#include <linux/atmdev.h>
15#include <linux/bitops.h>
16
17#include "resources.h"
18#include "signaling.h"
19
20
21#undef WAIT_FOR_DEMON /* #define this if system calls on SVC sockets
22 should block until the demon runs.
23 Danger: may cause nasty hangs if the demon
24 crashes. */
25
26#if 0
27#define DPRINTK(format,args...) printk(KERN_DEBUG format,##args)
28#else
29#define DPRINTK(format,args...)
30#endif
31
32
33struct atm_vcc *sigd = NULL;
34#ifdef WAIT_FOR_DEMON
35static DECLARE_WAIT_QUEUE_HEAD(sigd_sleep);
36#endif
37
38
39static void sigd_put_skb(struct sk_buff *skb)
40{
41#ifdef WAIT_FOR_DEMON
42 static unsigned long silence;
43 DECLARE_WAITQUEUE(wait,current);
44
45 add_wait_queue(&sigd_sleep,&wait);
46 while (!sigd) {
47 set_current_state(TASK_UNINTERRUPTIBLE);
48 if (time_after(jiffies, silence) || silence == 0) {
49 printk(KERN_INFO "atmsvc: waiting for signaling demon "
50 "...\n");
51 silence = (jiffies+30*HZ)|1;
52 }
53 schedule();
54 }
55 current->state = TASK_RUNNING;
56 remove_wait_queue(&sigd_sleep,&wait);
57#else
58 if (!sigd) {
59 printk(KERN_WARNING "atmsvc: no signaling demon\n");
60 kfree_skb(skb);
61 return;
62 }
63#endif
64 atm_force_charge(sigd,skb->truesize);
65 skb_queue_tail(&sk_atm(sigd)->sk_receive_queue,skb);
66 sk_atm(sigd)->sk_data_ready(sk_atm(sigd), skb->len);
67}
68
69
70static void modify_qos(struct atm_vcc *vcc,struct atmsvc_msg *msg)
71{
72 struct sk_buff *skb;
73
74 if (test_bit(ATM_VF_RELEASED,&vcc->flags) ||
75 !test_bit(ATM_VF_READY,&vcc->flags))
76 return;
77 msg->type = as_error;
78 if (!vcc->dev->ops->change_qos) msg->reply = -EOPNOTSUPP;
79 else {
80 /* should lock VCC */
81 msg->reply = vcc->dev->ops->change_qos(vcc,&msg->qos,
82 msg->reply);
83 if (!msg->reply) msg->type = as_okay;
84 }
85 /*
86 * Should probably just turn around the old skb. But the, the buffer
87 * space accounting needs to follow the change too. Maybe later.
88 */
89 while (!(skb = alloc_skb(sizeof(struct atmsvc_msg),GFP_KERNEL)))
90 schedule();
91 *(struct atmsvc_msg *) skb_put(skb,sizeof(struct atmsvc_msg)) = *msg;
92 sigd_put_skb(skb);
93}
94
95
96static int sigd_send(struct atm_vcc *vcc,struct sk_buff *skb)
97{
98 struct atmsvc_msg *msg;
99 struct atm_vcc *session_vcc;
100 struct sock *sk;
101
102 msg = (struct atmsvc_msg *) skb->data;
103 atomic_sub(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
104 DPRINTK("sigd_send %d (0x%lx)\n",(int) msg->type,
105 (unsigned long) msg->vcc);
106 vcc = *(struct atm_vcc **) &msg->vcc;
107 sk = sk_atm(vcc);
108
109 switch (msg->type) {
110 case as_okay:
111 sk->sk_err = -msg->reply;
112 clear_bit(ATM_VF_WAITING, &vcc->flags);
113 if (!*vcc->local.sas_addr.prv &&
114 !*vcc->local.sas_addr.pub) {
115 vcc->local.sas_family = AF_ATMSVC;
116 memcpy(vcc->local.sas_addr.prv,
117 msg->local.sas_addr.prv,ATM_ESA_LEN);
118 memcpy(vcc->local.sas_addr.pub,
119 msg->local.sas_addr.pub,ATM_E164_LEN+1);
120 }
121 session_vcc = vcc->session ? vcc->session : vcc;
122 if (session_vcc->vpi || session_vcc->vci) break;
123 session_vcc->itf = msg->pvc.sap_addr.itf;
124 session_vcc->vpi = msg->pvc.sap_addr.vpi;
125 session_vcc->vci = msg->pvc.sap_addr.vci;
126 if (session_vcc->vpi || session_vcc->vci)
127 session_vcc->qos = msg->qos;
128 break;
129 case as_error:
130 clear_bit(ATM_VF_REGIS,&vcc->flags);
131 clear_bit(ATM_VF_READY,&vcc->flags);
132 sk->sk_err = -msg->reply;
133 clear_bit(ATM_VF_WAITING, &vcc->flags);
134 break;
135 case as_indicate:
136 vcc = *(struct atm_vcc **) &msg->listen_vcc;
137 DPRINTK("as_indicate!!!\n");
138 lock_sock(sk);
139 if (sk_acceptq_is_full(sk)) {
140 sigd_enq(NULL,as_reject,vcc,NULL,NULL);
141 dev_kfree_skb(skb);
142 goto as_indicate_complete;
143 }
144 sk->sk_ack_backlog++;
145 skb_queue_tail(&sk->sk_receive_queue, skb);
146 DPRINTK("waking sk->sk_sleep 0x%p\n", sk->sk_sleep);
147 sk->sk_state_change(sk);
148as_indicate_complete:
149 release_sock(sk);
150 return 0;
151 case as_close:
152 set_bit(ATM_VF_RELEASED,&vcc->flags);
153 vcc_release_async(vcc, msg->reply);
154 goto out;
155 case as_modify:
156 modify_qos(vcc,msg);
157 break;
158 case as_addparty:
159 case as_dropparty:
160 sk->sk_err_soft = msg->reply; /* < 0 failure, otherwise ep_ref */
161 clear_bit(ATM_VF_WAITING, &vcc->flags);
162 break;
163 default:
164 printk(KERN_ALERT "sigd_send: bad message type %d\n",
165 (int) msg->type);
166 return -EINVAL;
167 }
168 sk->sk_state_change(sk);
169out:
170 dev_kfree_skb(skb);
171 return 0;
172}
173
174
175void sigd_enq2(struct atm_vcc *vcc,enum atmsvc_msg_type type,
176 struct atm_vcc *listen_vcc,const struct sockaddr_atmpvc *pvc,
177 const struct sockaddr_atmsvc *svc,const struct atm_qos *qos,int reply)
178{
179 struct sk_buff *skb;
180 struct atmsvc_msg *msg;
181 static unsigned session = 0;
182
183 DPRINTK("sigd_enq %d (0x%p)\n",(int) type,vcc);
184 while (!(skb = alloc_skb(sizeof(struct atmsvc_msg),GFP_KERNEL)))
185 schedule();
186 msg = (struct atmsvc_msg *) skb_put(skb,sizeof(struct atmsvc_msg));
187 memset(msg,0,sizeof(*msg));
188 msg->type = type;
189 *(struct atm_vcc **) &msg->vcc = vcc;
190 *(struct atm_vcc **) &msg->listen_vcc = listen_vcc;
191 msg->reply = reply;
192 if (qos) msg->qos = *qos;
193 if (vcc) msg->sap = vcc->sap;
194 if (svc) msg->svc = *svc;
195 if (vcc) msg->local = vcc->local;
196 if (pvc) msg->pvc = *pvc;
197 if (vcc) {
198 if (type == as_connect && test_bit(ATM_VF_SESSION, &vcc->flags))
199 msg->session = ++session;
200 /* every new pmp connect gets the next session number */
201 }
202 sigd_put_skb(skb);
203 if (vcc) set_bit(ATM_VF_REGIS,&vcc->flags);
204}
205
206
207void sigd_enq(struct atm_vcc *vcc,enum atmsvc_msg_type type,
208 struct atm_vcc *listen_vcc,const struct sockaddr_atmpvc *pvc,
209 const struct sockaddr_atmsvc *svc)
210{
211 sigd_enq2(vcc,type,listen_vcc,pvc,svc,vcc ? &vcc->qos : NULL,0);
212 /* other ISP applications may use "reply" */
213}
214
215
216static void purge_vcc(struct atm_vcc *vcc)
217{
218 if (sk_atm(vcc)->sk_family == PF_ATMSVC &&
219 !test_bit(ATM_VF_META,&vcc->flags)) {
220 set_bit(ATM_VF_RELEASED,&vcc->flags);
221 vcc_release_async(vcc, -EUNATCH);
222 }
223}
224
225
226static void sigd_close(struct atm_vcc *vcc)
227{
228 struct hlist_node *node;
229 struct sock *s;
230 int i;
231
232 DPRINTK("sigd_close\n");
233 sigd = NULL;
234 if (skb_peek(&sk_atm(vcc)->sk_receive_queue))
235 printk(KERN_ERR "sigd_close: closing with requests pending\n");
236 skb_queue_purge(&sk_atm(vcc)->sk_receive_queue);
237
238 read_lock(&vcc_sklist_lock);
239 for(i = 0; i < VCC_HTABLE_SIZE; ++i) {
240 struct hlist_head *head = &vcc_hash[i];
241
242 sk_for_each(s, node, head) {
243 struct atm_vcc *vcc = atm_sk(s);
244
245 if (vcc->dev)
246 purge_vcc(vcc);
247 }
248 }
249 read_unlock(&vcc_sklist_lock);
250}
251
252
253static struct atmdev_ops sigd_dev_ops = {
254 .close = sigd_close,
255 .send = sigd_send
256};
257
258
259static struct atm_dev sigd_dev = {
260 .ops = &sigd_dev_ops,
261 .type = "sig",
262 .number = 999,
263 .lock = SPIN_LOCK_UNLOCKED
264};
265
266
267int sigd_attach(struct atm_vcc *vcc)
268{
269 if (sigd) return -EADDRINUSE;
270 DPRINTK("sigd_attach\n");
271 sigd = vcc;
272 vcc->dev = &sigd_dev;
273 vcc_insert_socket(sk_atm(vcc));
274 set_bit(ATM_VF_META,&vcc->flags);
275 set_bit(ATM_VF_READY,&vcc->flags);
276#ifdef WAIT_FOR_DEMON
277 wake_up(&sigd_sleep);
278#endif
279 return 0;
280}
diff --git a/net/atm/signaling.h b/net/atm/signaling.h
new file mode 100644
index 000000000000..434ead455714
--- /dev/null
+++ b/net/atm/signaling.h
@@ -0,0 +1,30 @@
1/* net/atm/signaling.h - ATM signaling */
2
3/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
4
5
6#ifndef NET_ATM_SIGNALING_H
7#define NET_ATM_SIGNALING_H
8
9#include <linux/atm.h>
10#include <linux/atmdev.h>
11#include <linux/atmsvc.h>
12
13
14extern struct atm_vcc *sigd; /* needed in svc_release */
15
16
17/*
18 * sigd_enq is a wrapper for sigd_enq2, covering the more common cases, and
19 * avoiding huge lists of null values.
20 */
21
22void sigd_enq2(struct atm_vcc *vcc,enum atmsvc_msg_type type,
23 struct atm_vcc *listen_vcc,const struct sockaddr_atmpvc *pvc,
24 const struct sockaddr_atmsvc *svc,const struct atm_qos *qos,int reply);
25void sigd_enq(struct atm_vcc *vcc,enum atmsvc_msg_type type,
26 struct atm_vcc *listen_vcc,const struct sockaddr_atmpvc *pvc,
27 const struct sockaddr_atmsvc *svc);
28int sigd_attach(struct atm_vcc *vcc);
29
30#endif
diff --git a/net/atm/svc.c b/net/atm/svc.c
new file mode 100644
index 000000000000..02f5374a51f2
--- /dev/null
+++ b/net/atm/svc.c
@@ -0,0 +1,674 @@
1/* net/atm/svc.c - ATM SVC sockets */
2
3/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
4
5
6#include <linux/string.h>
7#include <linux/net.h> /* struct socket, struct proto_ops */
8#include <linux/errno.h> /* error codes */
9#include <linux/kernel.h> /* printk */
10#include <linux/skbuff.h>
11#include <linux/wait.h>
12#include <linux/sched.h> /* jiffies and HZ */
13#include <linux/fcntl.h> /* O_NONBLOCK */
14#include <linux/init.h>
15#include <linux/atm.h> /* ATM stuff */
16#include <linux/atmsap.h>
17#include <linux/atmsvc.h>
18#include <linux/atmdev.h>
19#include <linux/bitops.h>
20#include <net/sock.h> /* for sock_no_* */
21#include <asm/uaccess.h>
22
23#include "resources.h"
24#include "common.h" /* common for PVCs and SVCs */
25#include "signaling.h"
26#include "addr.h"
27
28
29#if 0
30#define DPRINTK(format,args...) printk(KERN_DEBUG format,##args)
31#else
32#define DPRINTK(format,args...)
33#endif
34
35
36static int svc_create(struct socket *sock,int protocol);
37
38
39/*
40 * Note: since all this is still nicely synchronized with the signaling demon,
41 * there's no need to protect sleep loops with clis. If signaling is
42 * moved into the kernel, that would change.
43 */
44
45
46static int svc_shutdown(struct socket *sock,int how)
47{
48 return 0;
49}
50
51
52static void svc_disconnect(struct atm_vcc *vcc)
53{
54 DEFINE_WAIT(wait);
55 struct sk_buff *skb;
56 struct sock *sk = sk_atm(vcc);
57
58 DPRINTK("svc_disconnect %p\n",vcc);
59 if (test_bit(ATM_VF_REGIS,&vcc->flags)) {
60 prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);
61 sigd_enq(vcc,as_close,NULL,NULL,NULL);
62 while (!test_bit(ATM_VF_RELEASED,&vcc->flags) && sigd) {
63 schedule();
64 prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);
65 }
66 finish_wait(sk->sk_sleep, &wait);
67 }
68 /* beware - socket is still in use by atmsigd until the last
69 as_indicate has been answered */
70 while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
71 atm_return(vcc, skb->truesize);
72 DPRINTK("LISTEN REL\n");
73 sigd_enq2(NULL,as_reject,vcc,NULL,NULL,&vcc->qos,0);
74 dev_kfree_skb(skb);
75 }
76 clear_bit(ATM_VF_REGIS, &vcc->flags);
77 /* ... may retry later */
78}
79
80
81static int svc_release(struct socket *sock)
82{
83 struct sock *sk = sock->sk;
84 struct atm_vcc *vcc;
85
86 if (sk) {
87 vcc = ATM_SD(sock);
88 DPRINTK("svc_release %p\n", vcc);
89 clear_bit(ATM_VF_READY, &vcc->flags);
90 /* VCC pointer is used as a reference, so we must not free it
91 (thereby subjecting it to re-use) before all pending connections
92 are closed */
93 svc_disconnect(vcc);
94 vcc_release(sock);
95 }
96 return 0;
97}
98
99
100static int svc_bind(struct socket *sock,struct sockaddr *sockaddr,
101 int sockaddr_len)
102{
103 DEFINE_WAIT(wait);
104 struct sock *sk = sock->sk;
105 struct sockaddr_atmsvc *addr;
106 struct atm_vcc *vcc;
107 int error;
108
109 if (sockaddr_len != sizeof(struct sockaddr_atmsvc))
110 return -EINVAL;
111 lock_sock(sk);
112 if (sock->state == SS_CONNECTED) {
113 error = -EISCONN;
114 goto out;
115 }
116 if (sock->state != SS_UNCONNECTED) {
117 error = -EINVAL;
118 goto out;
119 }
120 vcc = ATM_SD(sock);
121 if (test_bit(ATM_VF_SESSION, &vcc->flags)) {
122 error = -EINVAL;
123 goto out;
124 }
125 addr = (struct sockaddr_atmsvc *) sockaddr;
126 if (addr->sas_family != AF_ATMSVC) {
127 error = -EAFNOSUPPORT;
128 goto out;
129 }
130 clear_bit(ATM_VF_BOUND,&vcc->flags);
131 /* failing rebind will kill old binding */
132 /* @@@ check memory (de)allocation on rebind */
133 if (!test_bit(ATM_VF_HASQOS,&vcc->flags)) {
134 error = -EBADFD;
135 goto out;
136 }
137 vcc->local = *addr;
138 set_bit(ATM_VF_WAITING, &vcc->flags);
139 prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);
140 sigd_enq(vcc,as_bind,NULL,NULL,&vcc->local);
141 while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) {
142 schedule();
143 prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);
144 }
145 finish_wait(sk->sk_sleep, &wait);
146 clear_bit(ATM_VF_REGIS,&vcc->flags); /* doesn't count */
147 if (!sigd) {
148 error = -EUNATCH;
149 goto out;
150 }
151 if (!sk->sk_err)
152 set_bit(ATM_VF_BOUND,&vcc->flags);
153 error = -sk->sk_err;
154out:
155 release_sock(sk);
156 return error;
157}
158
159
160static int svc_connect(struct socket *sock,struct sockaddr *sockaddr,
161 int sockaddr_len,int flags)
162{
163 DEFINE_WAIT(wait);
164 struct sock *sk = sock->sk;
165 struct sockaddr_atmsvc *addr;
166 struct atm_vcc *vcc = ATM_SD(sock);
167 int error;
168
169 DPRINTK("svc_connect %p\n",vcc);
170 lock_sock(sk);
171 if (sockaddr_len != sizeof(struct sockaddr_atmsvc)) {
172 error = -EINVAL;
173 goto out;
174 }
175
176 switch (sock->state) {
177 default:
178 error = -EINVAL;
179 goto out;
180 case SS_CONNECTED:
181 error = -EISCONN;
182 goto out;
183 case SS_CONNECTING:
184 if (test_bit(ATM_VF_WAITING, &vcc->flags)) {
185 error = -EALREADY;
186 goto out;
187 }
188 sock->state = SS_UNCONNECTED;
189 if (sk->sk_err) {
190 error = -sk->sk_err;
191 goto out;
192 }
193 break;
194 case SS_UNCONNECTED:
195 addr = (struct sockaddr_atmsvc *) sockaddr;
196 if (addr->sas_family != AF_ATMSVC) {
197 error = -EAFNOSUPPORT;
198 goto out;
199 }
200 if (!test_bit(ATM_VF_HASQOS, &vcc->flags)) {
201 error = -EBADFD;
202 goto out;
203 }
204 if (vcc->qos.txtp.traffic_class == ATM_ANYCLASS ||
205 vcc->qos.rxtp.traffic_class == ATM_ANYCLASS) {
206 error = -EINVAL;
207 goto out;
208 }
209 if (!vcc->qos.txtp.traffic_class &&
210 !vcc->qos.rxtp.traffic_class) {
211 error = -EINVAL;
212 goto out;
213 }
214 vcc->remote = *addr;
215 set_bit(ATM_VF_WAITING, &vcc->flags);
216 prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
217 sigd_enq(vcc,as_connect,NULL,NULL,&vcc->remote);
218 if (flags & O_NONBLOCK) {
219 finish_wait(sk->sk_sleep, &wait);
220 sock->state = SS_CONNECTING;
221 error = -EINPROGRESS;
222 goto out;
223 }
224 error = 0;
225 while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) {
226 schedule();
227 if (!signal_pending(current)) {
228 prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
229 continue;
230 }
231 DPRINTK("*ABORT*\n");
232 /*
233 * This is tricky:
234 * Kernel ---close--> Demon
235 * Kernel <--close--- Demon
236 * or
237 * Kernel ---close--> Demon
238 * Kernel <--error--- Demon
239 * or
240 * Kernel ---close--> Demon
241 * Kernel <--okay---- Demon
242 * Kernel <--close--- Demon
243 */
244 sigd_enq(vcc,as_close,NULL,NULL,NULL);
245 while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) {
246 prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
247 schedule();
248 }
249 if (!sk->sk_err)
250 while (!test_bit(ATM_VF_RELEASED,&vcc->flags)
251 && sigd) {
252 prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
253 schedule();
254 }
255 clear_bit(ATM_VF_REGIS,&vcc->flags);
256 clear_bit(ATM_VF_RELEASED,&vcc->flags);
257 clear_bit(ATM_VF_CLOSE,&vcc->flags);
258 /* we're gone now but may connect later */
259 error = -EINTR;
260 break;
261 }
262 finish_wait(sk->sk_sleep, &wait);
263 if (error)
264 goto out;
265 if (!sigd) {
266 error = -EUNATCH;
267 goto out;
268 }
269 if (sk->sk_err) {
270 error = -sk->sk_err;
271 goto out;
272 }
273 }
274/*
275 * Not supported yet
276 *
277 * #ifndef CONFIG_SINGLE_SIGITF
278 */
279 vcc->qos.txtp.max_pcr = SELECT_TOP_PCR(vcc->qos.txtp);
280 vcc->qos.txtp.pcr = 0;
281 vcc->qos.txtp.min_pcr = 0;
282/*
283 * #endif
284 */
285 if (!(error = vcc_connect(sock, vcc->itf, vcc->vpi, vcc->vci)))
286 sock->state = SS_CONNECTED;
287 else
288 (void) svc_disconnect(vcc);
289out:
290 release_sock(sk);
291 return error;
292}
293
294
295static int svc_listen(struct socket *sock,int backlog)
296{
297 DEFINE_WAIT(wait);
298 struct sock *sk = sock->sk;
299 struct atm_vcc *vcc = ATM_SD(sock);
300 int error;
301
302 DPRINTK("svc_listen %p\n",vcc);
303 lock_sock(sk);
304 /* let server handle listen on unbound sockets */
305 if (test_bit(ATM_VF_SESSION,&vcc->flags)) {
306 error = -EINVAL;
307 goto out;
308 }
309 set_bit(ATM_VF_WAITING, &vcc->flags);
310 prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);
311 sigd_enq(vcc,as_listen,NULL,NULL,&vcc->local);
312 while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) {
313 schedule();
314 prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);
315 }
316 finish_wait(sk->sk_sleep, &wait);
317 if (!sigd) {
318 error = -EUNATCH;
319 goto out;
320 }
321 set_bit(ATM_VF_LISTEN,&vcc->flags);
322 sk->sk_max_ack_backlog = backlog > 0 ? backlog : ATM_BACKLOG_DEFAULT;
323 error = -sk->sk_err;
324out:
325 release_sock(sk);
326 return error;
327}
328
329
330static int svc_accept(struct socket *sock,struct socket *newsock,int flags)
331{
332 struct sock *sk = sock->sk;
333 struct sk_buff *skb;
334 struct atmsvc_msg *msg;
335 struct atm_vcc *old_vcc = ATM_SD(sock);
336 struct atm_vcc *new_vcc;
337 int error;
338
339 lock_sock(sk);
340
341 error = svc_create(newsock,0);
342 if (error)
343 goto out;
344
345 new_vcc = ATM_SD(newsock);
346
347 DPRINTK("svc_accept %p -> %p\n",old_vcc,new_vcc);
348 while (1) {
349 DEFINE_WAIT(wait);
350
351 prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
352 while (!(skb = skb_dequeue(&sk->sk_receive_queue)) &&
353 sigd) {
354 if (test_bit(ATM_VF_RELEASED,&old_vcc->flags)) break;
355 if (test_bit(ATM_VF_CLOSE,&old_vcc->flags)) {
356 error = -sk->sk_err;
357 break;
358 }
359 if (flags & O_NONBLOCK) {
360 error = -EAGAIN;
361 break;
362 }
363 release_sock(sk);
364 schedule();
365 lock_sock(sk);
366 if (signal_pending(current)) {
367 error = -ERESTARTSYS;
368 break;
369 }
370 prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
371 }
372 finish_wait(sk->sk_sleep, &wait);
373 if (error)
374 goto out;
375 if (!skb) {
376 error = -EUNATCH;
377 goto out;
378 }
379 msg = (struct atmsvc_msg *) skb->data;
380 new_vcc->qos = msg->qos;
381 set_bit(ATM_VF_HASQOS,&new_vcc->flags);
382 new_vcc->remote = msg->svc;
383 new_vcc->local = msg->local;
384 new_vcc->sap = msg->sap;
385 error = vcc_connect(newsock, msg->pvc.sap_addr.itf,
386 msg->pvc.sap_addr.vpi, msg->pvc.sap_addr.vci);
387 dev_kfree_skb(skb);
388 sk->sk_ack_backlog--;
389 if (error) {
390 sigd_enq2(NULL,as_reject,old_vcc,NULL,NULL,
391 &old_vcc->qos,error);
392 error = error == -EAGAIN ? -EBUSY : error;
393 goto out;
394 }
395 /* wait should be short, so we ignore the non-blocking flag */
396 set_bit(ATM_VF_WAITING, &new_vcc->flags);
397 prepare_to_wait(sk_atm(new_vcc)->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);
398 sigd_enq(new_vcc,as_accept,old_vcc,NULL,NULL);
399 while (test_bit(ATM_VF_WAITING, &new_vcc->flags) && sigd) {
400 release_sock(sk);
401 schedule();
402 lock_sock(sk);
403 prepare_to_wait(sk_atm(new_vcc)->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);
404 }
405 finish_wait(sk_atm(new_vcc)->sk_sleep, &wait);
406 if (!sigd) {
407 error = -EUNATCH;
408 goto out;
409 }
410 if (!sk_atm(new_vcc)->sk_err)
411 break;
412 if (sk_atm(new_vcc)->sk_err != ERESTARTSYS) {
413 error = -sk_atm(new_vcc)->sk_err;
414 goto out;
415 }
416 }
417 newsock->state = SS_CONNECTED;
418out:
419 release_sock(sk);
420 return error;
421}
422
423
424static int svc_getname(struct socket *sock,struct sockaddr *sockaddr,
425 int *sockaddr_len,int peer)
426{
427 struct sockaddr_atmsvc *addr;
428
429 *sockaddr_len = sizeof(struct sockaddr_atmsvc);
430 addr = (struct sockaddr_atmsvc *) sockaddr;
431 memcpy(addr,peer ? &ATM_SD(sock)->remote : &ATM_SD(sock)->local,
432 sizeof(struct sockaddr_atmsvc));
433 return 0;
434}
435
436
437int svc_change_qos(struct atm_vcc *vcc,struct atm_qos *qos)
438{
439 struct sock *sk = sk_atm(vcc);
440 DEFINE_WAIT(wait);
441
442 set_bit(ATM_VF_WAITING, &vcc->flags);
443 prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);
444 sigd_enq2(vcc,as_modify,NULL,NULL,&vcc->local,qos,0);
445 while (test_bit(ATM_VF_WAITING, &vcc->flags) &&
446 !test_bit(ATM_VF_RELEASED, &vcc->flags) && sigd) {
447 schedule();
448 prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);
449 }
450 finish_wait(sk->sk_sleep, &wait);
451 if (!sigd) return -EUNATCH;
452 return -sk->sk_err;
453}
454
455
456static int svc_setsockopt(struct socket *sock, int level, int optname,
457 char __user *optval, int optlen)
458{
459 struct sock *sk = sock->sk;
460 struct atm_vcc *vcc = ATM_SD(sock);
461 int value, error = 0;
462
463 lock_sock(sk);
464 switch (optname) {
465 case SO_ATMSAP:
466 if (level != SOL_ATM || optlen != sizeof(struct atm_sap)) {
467 error = -EINVAL;
468 goto out;
469 }
470 if (copy_from_user(&vcc->sap, optval, optlen)) {
471 error = -EFAULT;
472 goto out;
473 }
474 set_bit(ATM_VF_HASSAP, &vcc->flags);
475 break;
476 case SO_MULTIPOINT:
477 if (level != SOL_ATM || optlen != sizeof(int)) {
478 error = -EINVAL;
479 goto out;
480 }
481 if (get_user(value, (int __user *) optval)) {
482 error = -EFAULT;
483 goto out;
484 }
485 if (value == 1) {
486 set_bit(ATM_VF_SESSION, &vcc->flags);
487 } else if (value == 0) {
488 clear_bit(ATM_VF_SESSION, &vcc->flags);
489 } else {
490 error = -EINVAL;
491 }
492 break;
493 default:
494 error = vcc_setsockopt(sock, level, optname,
495 optval, optlen);
496 }
497
498out:
499 release_sock(sk);
500 return error;
501}
502
503
504static int svc_getsockopt(struct socket *sock,int level,int optname,
505 char __user *optval,int __user *optlen)
506{
507 struct sock *sk = sock->sk;
508 int error = 0, len;
509
510 lock_sock(sk);
511 if (!__SO_LEVEL_MATCH(optname, level) || optname != SO_ATMSAP) {
512 error = vcc_getsockopt(sock, level, optname, optval, optlen);
513 goto out;
514 }
515 if (get_user(len, optlen)) {
516 error = -EFAULT;
517 goto out;
518 }
519 if (len != sizeof(struct atm_sap)) {
520 error = -EINVAL;
521 goto out;
522 }
523 if (copy_to_user(optval, &ATM_SD(sock)->sap, sizeof(struct atm_sap))) {
524 error = -EFAULT;
525 goto out;
526 }
527out:
528 release_sock(sk);
529 return error;
530}
531
532
533static int svc_addparty(struct socket *sock, struct sockaddr *sockaddr,
534 int sockaddr_len, int flags)
535{
536 DEFINE_WAIT(wait);
537 struct sock *sk = sock->sk;
538 struct atm_vcc *vcc = ATM_SD(sock);
539 int error;
540
541 lock_sock(sk);
542 set_bit(ATM_VF_WAITING, &vcc->flags);
543 prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
544 sigd_enq(vcc, as_addparty, NULL, NULL,
545 (struct sockaddr_atmsvc *) sockaddr);
546 if (flags & O_NONBLOCK) {
547 finish_wait(sk->sk_sleep, &wait);
548 error = -EINPROGRESS;
549 goto out;
550 }
551 DPRINTK("svc_addparty added wait queue\n");
552 while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) {
553 schedule();
554 prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
555 }
556 finish_wait(sk->sk_sleep, &wait);
557 error = xchg(&sk->sk_err_soft, 0);
558out:
559 release_sock(sk);
560 return error;
561}
562
563
564static int svc_dropparty(struct socket *sock, int ep_ref)
565{
566 DEFINE_WAIT(wait);
567 struct sock *sk = sock->sk;
568 struct atm_vcc *vcc = ATM_SD(sock);
569 int error;
570
571 lock_sock(sk);
572 set_bit(ATM_VF_WAITING, &vcc->flags);
573 prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
574 sigd_enq2(vcc, as_dropparty, NULL, NULL, NULL, NULL, ep_ref);
575 while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) {
576 schedule();
577 prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
578 }
579 finish_wait(sk->sk_sleep, &wait);
580 if (!sigd) {
581 error = -EUNATCH;
582 goto out;
583 }
584 error = xchg(&sk->sk_err_soft, 0);
585out:
586 release_sock(sk);
587 return error;
588}
589
590
591static int svc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
592{
593 int error, ep_ref;
594 struct sockaddr_atmsvc sa;
595 struct atm_vcc *vcc = ATM_SD(sock);
596
597 switch (cmd) {
598 case ATM_ADDPARTY:
599 if (!test_bit(ATM_VF_SESSION, &vcc->flags))
600 return -EINVAL;
601 if (copy_from_user(&sa, (void __user *) arg, sizeof(sa)))
602 return -EFAULT;
603 error = svc_addparty(sock, (struct sockaddr *) &sa, sizeof(sa), 0);
604 break;
605 case ATM_DROPPARTY:
606 if (!test_bit(ATM_VF_SESSION, &vcc->flags))
607 return -EINVAL;
608 if (copy_from_user(&ep_ref, (void __user *) arg, sizeof(int)))
609 return -EFAULT;
610 error = svc_dropparty(sock, ep_ref);
611 break;
612 default:
613 error = vcc_ioctl(sock, cmd, arg);
614 }
615
616 return error;
617}
618
619static struct proto_ops svc_proto_ops = {
620 .family = PF_ATMSVC,
621 .owner = THIS_MODULE,
622
623 .release = svc_release,
624 .bind = svc_bind,
625 .connect = svc_connect,
626 .socketpair = sock_no_socketpair,
627 .accept = svc_accept,
628 .getname = svc_getname,
629 .poll = vcc_poll,
630 .ioctl = svc_ioctl,
631 .listen = svc_listen,
632 .shutdown = svc_shutdown,
633 .setsockopt = svc_setsockopt,
634 .getsockopt = svc_getsockopt,
635 .sendmsg = vcc_sendmsg,
636 .recvmsg = vcc_recvmsg,
637 .mmap = sock_no_mmap,
638 .sendpage = sock_no_sendpage,
639};
640
641
642static int svc_create(struct socket *sock,int protocol)
643{
644 int error;
645
646 sock->ops = &svc_proto_ops;
647 error = vcc_create(sock, protocol, AF_ATMSVC);
648 if (error) return error;
649 ATM_SD(sock)->local.sas_family = AF_ATMSVC;
650 ATM_SD(sock)->remote.sas_family = AF_ATMSVC;
651 return 0;
652}
653
654
655static struct net_proto_family svc_family_ops = {
656 .family = PF_ATMSVC,
657 .create = svc_create,
658 .owner = THIS_MODULE,
659};
660
661
662/*
663 * Initialize the ATM SVC protocol family
664 */
665
666int __init atmsvc_init(void)
667{
668 return sock_register(&svc_family_ops);
669}
670
671void atmsvc_exit(void)
672{
673 sock_unregister(PF_ATMSVC);
674}