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/capability.h>
7 #include <linux/seq_file.h>
9 /* We are an ethernet device */
10 #include <linux/if_ether.h>
11 #include <linux/netdevice.h>
12 #include <linux/etherdevice.h>
14 #include <linux/skbuff.h>
16 #include <asm/byteorder.h>
17 #include <asm/uaccess.h>
18 #include <net/checksum.h> /* for ip_fast_csum() */
21 #include <linux/proc_fs.h>
24 #include <linux/atmdev.h>
25 #include <linux/atmlec.h>
26 #include <linux/atmmpc.h>
28 #include <linux/module.h>
32 #include "resources.h"
35 * mpc.c: Implementation of MPOA client kernel part
39 #define dprintk printk /* debug */
41 #define dprintk(format,args...)
45 #define ddprintk printk /* more debug */
47 #define ddprintk(format,args...)
52 #define MPOA_TAG_LEN 4
54 /* mpc_daemon -> kernel */
55 static void MPOA_trigger_rcvd (struct k_message
*msg
, struct mpoa_client
*mpc
);
56 static void MPOA_res_reply_rcvd(struct k_message
*msg
, struct mpoa_client
*mpc
);
57 static void ingress_purge_rcvd(struct k_message
*msg
, struct mpoa_client
*mpc
);
58 static void egress_purge_rcvd(struct k_message
*msg
, struct mpoa_client
*mpc
);
59 static void mps_death(struct k_message
*msg
, struct mpoa_client
*mpc
);
60 static void clean_up(struct k_message
*msg
, struct mpoa_client
*mpc
, int action
);
61 static void MPOA_cache_impos_rcvd(struct k_message
*msg
, struct mpoa_client
*mpc
);
62 static void set_mpc_ctrl_addr_rcvd(struct k_message
*mesg
, struct mpoa_client
*mpc
);
63 static void set_mps_mac_addr_rcvd(struct k_message
*mesg
, struct mpoa_client
*mpc
);
65 static const uint8_t *copy_macs(struct mpoa_client
*mpc
,
66 const uint8_t *router_mac
,
67 const uint8_t *tlvs
, uint8_t mps_macs
,
69 static void purge_egress_shortcut(struct atm_vcc
*vcc
, eg_cache_entry
*entry
);
71 static void send_set_mps_ctrl_addr(const char *addr
, struct mpoa_client
*mpc
);
72 static void mpoad_close(struct atm_vcc
*vcc
);
73 static int msg_from_mpoad(struct atm_vcc
*vcc
, struct sk_buff
*skb
);
75 static void mpc_push(struct atm_vcc
*vcc
, struct sk_buff
*skb
);
76 static int mpc_send_packet(struct sk_buff
*skb
, struct net_device
*dev
);
77 static int mpoa_event_listener(struct notifier_block
*mpoa_notifier
, unsigned long event
, void *dev
);
78 static void mpc_timer_refresh(void);
79 static void mpc_cache_check( unsigned long checking_time
);
81 static struct llc_snap_hdr llc_snap_mpoa_ctrl
= {
84 {0x00, 0x03} /* For MPOA control PDUs */
86 static struct llc_snap_hdr llc_snap_mpoa_data
= {
89 {0x08, 0x00} /* This is for IP PDUs only */
91 static struct llc_snap_hdr llc_snap_mpoa_data_tagged
= {
94 {0x88, 0x4c} /* This is for tagged data PDUs */
97 static struct notifier_block mpoa_notifier
= {
103 struct mpoa_client
*mpcs
= NULL
; /* FIXME */
104 static struct atm_mpoa_qos
*qos_head
= NULL
;
105 static DEFINE_TIMER(mpc_timer
, NULL
, 0, 0);
108 static struct mpoa_client
*find_mpc_by_itfnum(int itf
)
110 struct mpoa_client
*mpc
;
112 mpc
= mpcs
; /* our global linked list */
113 while (mpc
!= NULL
) {
114 if (mpc
->dev_num
== itf
)
119 return NULL
; /* not found */
122 static struct mpoa_client
*find_mpc_by_vcc(struct atm_vcc
*vcc
)
124 struct mpoa_client
*mpc
;
126 mpc
= mpcs
; /* our global linked list */
127 while (mpc
!= NULL
) {
128 if (mpc
->mpoad_vcc
== vcc
)
133 return NULL
; /* not found */
136 static struct mpoa_client
*find_mpc_by_lec(struct net_device
*dev
)
138 struct mpoa_client
*mpc
;
140 mpc
= mpcs
; /* our global linked list */
141 while (mpc
!= NULL
) {
147 return NULL
; /* not found */
151 * Functions for managing QoS list
155 * Overwrites the old entry or makes a new one.
157 struct atm_mpoa_qos
*atm_mpoa_add_qos(__be32 dst_ip
, struct atm_qos
*qos
)
159 struct atm_mpoa_qos
*entry
;
161 entry
= atm_mpoa_search_qos(dst_ip
);
167 entry
= kmalloc(sizeof(struct atm_mpoa_qos
), GFP_KERNEL
);
169 printk("mpoa: atm_mpoa_add_qos: out of memory\n");
173 entry
->ipaddr
= dst_ip
;
176 entry
->next
= qos_head
;
182 struct atm_mpoa_qos
*atm_mpoa_search_qos(__be32 dst_ip
)
184 struct atm_mpoa_qos
*qos
;
187 while( qos
!= NULL
){
188 if(qos
->ipaddr
== dst_ip
) {
198 * Returns 0 for failure
200 int atm_mpoa_delete_qos(struct atm_mpoa_qos
*entry
)
203 struct atm_mpoa_qos
*curr
;
205 if (entry
== NULL
) return 0;
206 if (entry
== qos_head
) {
207 qos_head
= qos_head
->next
;
213 while (curr
!= NULL
) {
214 if (curr
->next
== entry
) {
215 curr
->next
= entry
->next
;
225 /* this is buggered - we need locking for qos_head */
226 void atm_mpoa_disp_qos(struct seq_file
*m
)
228 struct atm_mpoa_qos
*qos
;
231 seq_printf(m
, "QoS entries for shortcuts:\n");
232 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");
234 while (qos
!= NULL
) {
235 seq_printf(m
, "%u.%u.%u.%u\n %-7d %-7d %-7d %-7d %-7d\n %-7d %-7d %-7d %-7d %-7d\n",
236 NIPQUAD(qos
->ipaddr
),
237 qos
->qos
.txtp
.max_pcr
, qos
->qos
.txtp
.pcr
, qos
->qos
.txtp
.min_pcr
, qos
->qos
.txtp
.max_cdv
, qos
->qos
.txtp
.max_sdu
,
238 qos
->qos
.rxtp
.max_pcr
, qos
->qos
.rxtp
.pcr
, qos
->qos
.rxtp
.min_pcr
, qos
->qos
.rxtp
.max_cdv
, qos
->qos
.rxtp
.max_sdu
);
243 static struct net_device
*find_lec_by_itfnum(int itf
)
245 struct net_device
*dev
;
248 sprintf(name
, "lec%d", itf
);
249 dev
= dev_get_by_name(&init_net
, name
);
254 static struct mpoa_client
*alloc_mpc(void)
256 struct mpoa_client
*mpc
;
258 mpc
= kzalloc(sizeof (struct mpoa_client
), GFP_KERNEL
);
261 rwlock_init(&mpc
->ingress_lock
);
262 rwlock_init(&mpc
->egress_lock
);
264 atm_mpoa_init_cache(mpc
);
266 mpc
->parameters
.mpc_p1
= MPC_P1
;
267 mpc
->parameters
.mpc_p2
= MPC_P2
;
268 memset(mpc
->parameters
.mpc_p3
,0,sizeof(mpc
->parameters
.mpc_p3
));
269 mpc
->parameters
.mpc_p4
= MPC_P4
;
270 mpc
->parameters
.mpc_p5
= MPC_P5
;
271 mpc
->parameters
.mpc_p6
= MPC_P6
;
280 * start_mpc() puts the MPC on line. All the packets destined
281 * to the lec underneath us are now being monitored and
282 * shortcuts will be established.
285 static void start_mpc(struct mpoa_client
*mpc
, struct net_device
*dev
)
288 dprintk("mpoa: (%s) start_mpc:\n", mpc
->dev
->name
);
289 if (dev
->hard_start_xmit
== NULL
) {
290 printk("mpoa: (%s) start_mpc: dev->hard_start_xmit == NULL, not starting\n",
294 mpc
->old_hard_start_xmit
= dev
->hard_start_xmit
;
295 dev
->hard_start_xmit
= mpc_send_packet
;
300 static void stop_mpc(struct mpoa_client
*mpc
)
303 dprintk("mpoa: (%s) stop_mpc:", mpc
->dev
->name
);
305 /* Lets not nullify lec device's dev->hard_start_xmit */
306 if (mpc
->dev
->hard_start_xmit
!= mpc_send_packet
) {
307 dprintk(" mpc already stopped, not fatal\n");
311 mpc
->dev
->hard_start_xmit
= mpc
->old_hard_start_xmit
;
312 mpc
->old_hard_start_xmit
= NULL
;
313 /* close_shortcuts(mpc); ??? FIXME */
318 static const char *mpoa_device_type_string(char type
) __attribute__ ((unused
));
320 static const char *mpoa_device_type_string(char type
)
324 return "non-MPOA device";
333 return "both MPS and MPC";
336 return "unspecified (non-MPOA) device";
340 return ""; /* not reached */
344 * lec device calls this via its dev->priv->lane2_ops->associate_indicator()
345 * when it sees a TLV in LE_ARP packet.
346 * We fill in the pointer above when we see a LANE2 lec initializing
347 * See LANE2 spec 3.1.5
349 * Quite a big and ugly function but when you look at it
350 * all it does is to try to locate and parse MPOA Device
352 * We give our lec a pointer to this function and when the
353 * lec sees a TLV it uses the pointer to call this function.
356 static void lane2_assoc_ind(struct net_device
*dev
, const u8
*mac_addr
,
357 const u8
*tlvs
, u32 sizeoftlvs
)
360 uint8_t length
, mpoa_device_type
, number_of_mps_macs
;
361 const uint8_t *end_of_tlvs
;
362 struct mpoa_client
*mpc
;
364 mpoa_device_type
= number_of_mps_macs
= 0; /* silence gcc */
365 dprintk("mpoa: (%s) lane2_assoc_ind: received TLV(s), ", dev
->name
);
366 dprintk("total length of all TLVs %d\n", sizeoftlvs
);
367 mpc
= find_mpc_by_lec(dev
); /* Sampo-Fix: moved here from below */
369 printk("mpoa: (%s) lane2_assoc_ind: no mpc\n", dev
->name
);
372 end_of_tlvs
= tlvs
+ sizeoftlvs
;
373 while (end_of_tlvs
- tlvs
>= 5) {
374 type
= (tlvs
[0] << 24) | (tlvs
[1] << 16) | (tlvs
[2] << 8) | tlvs
[3];
377 dprintk(" type 0x%x length %02x\n", type
, length
);
378 if (tlvs
+ length
> end_of_tlvs
) {
379 printk("TLV value extends past its buffer, aborting parse\n");
384 printk("mpoa: (%s) lane2_assoc_ind: TLV type was 0, returning\n", dev
->name
);
388 if (type
!= TLV_MPOA_DEVICE_TYPE
) {
390 continue; /* skip other TLVs */
392 mpoa_device_type
= *tlvs
++;
393 number_of_mps_macs
= *tlvs
++;
394 dprintk("mpoa: (%s) MPOA device type '%s', ", dev
->name
, mpoa_device_type_string(mpoa_device_type
));
395 if (mpoa_device_type
== MPS_AND_MPC
&&
396 length
< (42 + number_of_mps_macs
*ETH_ALEN
)) { /* :) */
397 printk("\nmpoa: (%s) lane2_assoc_ind: short MPOA Device Type TLV\n",
401 if ((mpoa_device_type
== MPS
|| mpoa_device_type
== MPC
)
402 && length
< 22 + number_of_mps_macs
*ETH_ALEN
) {
403 printk("\nmpoa: (%s) lane2_assoc_ind: short MPOA Device Type TLV\n",
407 if (mpoa_device_type
!= MPS
&& mpoa_device_type
!= MPS_AND_MPC
) {
408 dprintk("ignoring non-MPS device\n");
409 if (mpoa_device_type
== MPC
) tlvs
+= 20;
410 continue; /* we are only interested in MPSs */
412 if (number_of_mps_macs
== 0 && mpoa_device_type
== MPS_AND_MPC
) {
413 printk("\nmpoa: (%s) lane2_assoc_ind: MPS_AND_MPC has zero MACs\n", dev
->name
);
414 continue; /* someone should read the spec */
416 dprintk("this MPS has %d MAC addresses\n", number_of_mps_macs
);
418 /* ok, now we can go and tell our daemon the control address of MPS */
419 send_set_mps_ctrl_addr(tlvs
, mpc
);
421 tlvs
= copy_macs(mpc
, mac_addr
, tlvs
, number_of_mps_macs
, mpoa_device_type
);
422 if (tlvs
== NULL
) return;
424 if (end_of_tlvs
- tlvs
!= 0)
425 printk("mpoa: (%s) lane2_assoc_ind: ignoring %Zd bytes of trailing TLV carbage\n",
426 dev
->name
, end_of_tlvs
- tlvs
);
431 * Store at least advertizing router's MAC address
432 * plus the possible MAC address(es) to mpc->mps_macs.
433 * For a freshly allocated MPOA client mpc->mps_macs == 0.
435 static const uint8_t *copy_macs(struct mpoa_client
*mpc
,
436 const uint8_t *router_mac
,
437 const uint8_t *tlvs
, uint8_t mps_macs
,
441 num_macs
= (mps_macs
> 1) ? mps_macs
: 1;
443 if (mpc
->number_of_mps_macs
!= num_macs
) { /* need to reallocate? */
444 if (mpc
->number_of_mps_macs
!= 0) kfree(mpc
->mps_macs
);
445 mpc
->number_of_mps_macs
= 0;
446 mpc
->mps_macs
= kmalloc(num_macs
*ETH_ALEN
, GFP_KERNEL
);
447 if (mpc
->mps_macs
== NULL
) {
448 printk("mpoa: (%s) copy_macs: out of mem\n", mpc
->dev
->name
);
452 memcpy(mpc
->mps_macs
, router_mac
, ETH_ALEN
);
453 tlvs
+= 20; if (device_type
== MPS_AND_MPC
) tlvs
+= 20;
455 memcpy(mpc
->mps_macs
, tlvs
, mps_macs
*ETH_ALEN
);
456 tlvs
+= mps_macs
*ETH_ALEN
;
457 mpc
->number_of_mps_macs
= num_macs
;
462 static int send_via_shortcut(struct sk_buff
*skb
, struct mpoa_client
*mpc
)
464 in_cache_entry
*entry
;
470 struct llc_snap_hdr hdr
;
472 } tagged_llc_snap_hdr
= {
473 {0xaa, 0xaa, 0x03, {0x00, 0x00, 0x00}, {0x88, 0x4c}},
477 buff
= skb
->data
+ mpc
->dev
->hard_header_len
;
478 iph
= (struct iphdr
*)buff
;
481 ddprintk("mpoa: (%s) send_via_shortcut: ipaddr 0x%x\n", mpc
->dev
->name
, ipaddr
);
483 entry
= mpc
->in_ops
->get(ipaddr
, mpc
);
485 entry
= mpc
->in_ops
->add_entry(ipaddr
, mpc
);
486 if (entry
!= NULL
) mpc
->in_ops
->put(entry
);
489 if (mpc
->in_ops
->cache_hit(entry
, mpc
) != OPEN
){ /* threshold not exceeded or VCC not ready */
490 ddprintk("mpoa: (%s) send_via_shortcut: cache_hit: returns != OPEN\n", mpc
->dev
->name
);
491 mpc
->in_ops
->put(entry
);
495 ddprintk("mpoa: (%s) send_via_shortcut: using shortcut\n", mpc
->dev
->name
);
496 /* MPOA spec A.1.4, MPOA client must decrement IP ttl at least by one */
498 ddprintk("mpoa: (%s) send_via_shortcut: IP ttl = %u, using LANE\n", mpc
->dev
->name
, iph
->ttl
);
499 mpc
->in_ops
->put(entry
);
504 iph
->check
= ip_fast_csum((unsigned char *)iph
, iph
->ihl
);
506 if (entry
->ctrl_info
.tag
!= 0) {
507 ddprintk("mpoa: (%s) send_via_shortcut: adding tag 0x%x\n", mpc
->dev
->name
, entry
->ctrl_info
.tag
);
508 tagged_llc_snap_hdr
.tag
= entry
->ctrl_info
.tag
;
509 skb_pull(skb
, ETH_HLEN
); /* get rid of Eth header */
510 skb_push(skb
, sizeof(tagged_llc_snap_hdr
)); /* add LLC/SNAP header */
511 skb_copy_to_linear_data(skb
, &tagged_llc_snap_hdr
,
512 sizeof(tagged_llc_snap_hdr
));
514 skb_pull(skb
, ETH_HLEN
); /* get rid of Eth header */
515 skb_push(skb
, sizeof(struct llc_snap_hdr
)); /* add LLC/SNAP header + tag */
516 skb_copy_to_linear_data(skb
, &llc_snap_mpoa_data
,
517 sizeof(struct llc_snap_hdr
));
520 atomic_add(skb
->truesize
, &sk_atm(entry
->shortcut
)->sk_wmem_alloc
);
521 ATM_SKB(skb
)->atm_options
= entry
->shortcut
->atm_options
;
522 entry
->shortcut
->send(entry
->shortcut
, skb
);
523 entry
->packets_fwded
++;
524 mpc
->in_ops
->put(entry
);
530 * Probably needs some error checks and locking, not sure...
532 static int mpc_send_packet(struct sk_buff
*skb
, struct net_device
*dev
)
535 struct mpoa_client
*mpc
;
539 mpc
= find_mpc_by_lec(dev
); /* this should NEVER fail */
541 printk("mpoa: (%s) mpc_send_packet: no MPC found\n", dev
->name
);
545 eth
= (struct ethhdr
*)skb
->data
;
546 if (eth
->h_proto
!= htons(ETH_P_IP
))
547 goto non_ip
; /* Multi-Protocol Over ATM :-) */
549 /* Weed out funny packets (e.g., AF_PACKET or raw). */
550 if (skb
->len
< ETH_HLEN
+ sizeof(struct iphdr
))
552 skb_set_network_header(skb
, ETH_HLEN
);
553 if (skb
->len
< ETH_HLEN
+ ip_hdr(skb
)->ihl
* 4 || ip_hdr(skb
)->ihl
< 5)
556 while (i
< mpc
->number_of_mps_macs
) {
557 if (!compare_ether_addr(eth
->h_dest
, (mpc
->mps_macs
+ i
*ETH_ALEN
)))
558 if ( send_via_shortcut(skb
, mpc
) == 0 ) /* try shortcut */
559 return 0; /* success! */
564 retval
= mpc
->old_hard_start_xmit(skb
,dev
);
569 static int atm_mpoa_vcc_attach(struct atm_vcc
*vcc
, void __user
*arg
)
572 struct mpoa_client
*mpc
;
573 struct atmmpc_ioc ioc_data
;
574 in_cache_entry
*in_entry
;
577 bytes_left
= copy_from_user(&ioc_data
, arg
, sizeof(struct atmmpc_ioc
));
578 if (bytes_left
!= 0) {
579 printk("mpoa: mpc_vcc_attach: Short read (missed %d bytes) from userland\n", bytes_left
);
582 ipaddr
= ioc_data
.ipaddr
;
583 if (ioc_data
.dev_num
< 0 || ioc_data
.dev_num
>= MAX_LEC_ITF
)
586 mpc
= find_mpc_by_itfnum(ioc_data
.dev_num
);
590 if (ioc_data
.type
== MPC_SOCKET_INGRESS
) {
591 in_entry
= mpc
->in_ops
->get(ipaddr
, mpc
);
592 if (in_entry
== NULL
|| in_entry
->entry_state
< INGRESS_RESOLVED
) {
593 printk("mpoa: (%s) mpc_vcc_attach: did not find RESOLVED entry from ingress cache\n",
595 if (in_entry
!= NULL
) mpc
->in_ops
->put(in_entry
);
598 printk("mpoa: (%s) mpc_vcc_attach: attaching ingress SVC, entry = %u.%u.%u.%u\n",
599 mpc
->dev
->name
, NIPQUAD(in_entry
->ctrl_info
.in_dst_ip
));
600 in_entry
->shortcut
= vcc
;
601 mpc
->in_ops
->put(in_entry
);
603 printk("mpoa: (%s) mpc_vcc_attach: attaching egress SVC\n", mpc
->dev
->name
);
606 vcc
->proto_data
= mpc
->dev
;
607 vcc
->push
= mpc_push
;
615 static void mpc_vcc_close(struct atm_vcc
*vcc
, struct net_device
*dev
)
617 struct mpoa_client
*mpc
;
618 in_cache_entry
*in_entry
;
619 eg_cache_entry
*eg_entry
;
621 mpc
= find_mpc_by_lec(dev
);
623 printk("mpoa: (%s) mpc_vcc_close: close for unknown MPC\n", dev
->name
);
627 dprintk("mpoa: (%s) mpc_vcc_close:\n", dev
->name
);
628 in_entry
= mpc
->in_ops
->get_by_vcc(vcc
, mpc
);
630 dprintk("mpoa: (%s) mpc_vcc_close: ingress SVC closed ip = %u.%u.%u.%u\n",
631 mpc
->dev
->name
, NIPQUAD(in_entry
->ctrl_info
.in_dst_ip
));
632 in_entry
->shortcut
= NULL
;
633 mpc
->in_ops
->put(in_entry
);
635 eg_entry
= mpc
->eg_ops
->get_by_vcc(vcc
, mpc
);
637 dprintk("mpoa: (%s) mpc_vcc_close: egress SVC closed\n", mpc
->dev
->name
);
638 eg_entry
->shortcut
= NULL
;
639 mpc
->eg_ops
->put(eg_entry
);
642 if (in_entry
== NULL
&& eg_entry
== NULL
)
643 dprintk("mpoa: (%s) mpc_vcc_close: unused vcc closed\n", dev
->name
);
648 static void mpc_push(struct atm_vcc
*vcc
, struct sk_buff
*skb
)
650 struct net_device
*dev
= (struct net_device
*)vcc
->proto_data
;
651 struct sk_buff
*new_skb
;
653 struct mpoa_client
*mpc
;
657 ddprintk("mpoa: (%s) mpc_push:\n", dev
->name
);
659 dprintk("mpoa: (%s) mpc_push: null skb, closing VCC\n", dev
->name
);
660 mpc_vcc_close(vcc
, dev
);
665 if (memcmp(skb
->data
, &llc_snap_mpoa_ctrl
, sizeof(struct llc_snap_hdr
)) == 0) {
666 struct sock
*sk
= sk_atm(vcc
);
668 dprintk("mpoa: (%s) mpc_push: control packet arrived\n", dev
->name
);
669 /* Pass control packets to daemon */
670 skb_queue_tail(&sk
->sk_receive_queue
, skb
);
671 sk
->sk_data_ready(sk
, skb
->len
);
675 /* data coming over the shortcut */
676 atm_return(vcc
, skb
->truesize
);
678 mpc
= find_mpc_by_lec(dev
);
680 printk("mpoa: (%s) mpc_push: unknown MPC\n", dev
->name
);
684 if (memcmp(skb
->data
, &llc_snap_mpoa_data_tagged
, sizeof(struct llc_snap_hdr
)) == 0) { /* MPOA tagged data */
685 ddprintk("mpoa: (%s) mpc_push: tagged data packet arrived\n", dev
->name
);
687 } else if (memcmp(skb
->data
, &llc_snap_mpoa_data
, sizeof(struct llc_snap_hdr
)) == 0) { /* MPOA data */
688 printk("mpoa: (%s) mpc_push: non-tagged data packet arrived\n", dev
->name
);
689 printk(" mpc_push: non-tagged data unsupported, purging\n");
690 dev_kfree_skb_any(skb
);
693 printk("mpoa: (%s) mpc_push: garbage arrived, purging\n", dev
->name
);
694 dev_kfree_skb_any(skb
);
698 tmp
= skb
->data
+ sizeof(struct llc_snap_hdr
);
699 tag
= *(__be32
*)tmp
;
701 eg
= mpc
->eg_ops
->get_by_tag(tag
, mpc
);
703 printk("mpoa: (%s) mpc_push: Didn't find egress cache entry, tag = %u\n",
705 purge_egress_shortcut(vcc
, NULL
);
706 dev_kfree_skb_any(skb
);
711 * See if ingress MPC is using shortcut we opened as a return channel.
712 * This means we have a bi-directional vcc opened by us.
714 if (eg
->shortcut
== NULL
) {
716 printk("mpoa: (%s) mpc_push: egress SVC in use\n", dev
->name
);
719 skb_pull(skb
, sizeof(struct llc_snap_hdr
) + sizeof(tag
)); /* get rid of LLC/SNAP header */
720 new_skb
= skb_realloc_headroom(skb
, eg
->ctrl_info
.DH_length
); /* LLC/SNAP is shorter than MAC header :( */
721 dev_kfree_skb_any(skb
);
722 if (new_skb
== NULL
){
723 mpc
->eg_ops
->put(eg
);
726 skb_push(new_skb
, eg
->ctrl_info
.DH_length
); /* add MAC header */
727 skb_copy_to_linear_data(new_skb
, eg
->ctrl_info
.DLL_header
,
728 eg
->ctrl_info
.DH_length
);
729 new_skb
->protocol
= eth_type_trans(new_skb
, dev
);
730 skb_reset_network_header(new_skb
);
732 eg
->latest_ip_addr
= ip_hdr(new_skb
)->saddr
;
734 mpc
->eg_ops
->put(eg
);
736 memset(ATM_SKB(skb
), 0, sizeof(struct atm_skb_data
));
742 static struct atmdev_ops mpc_ops
= { /* only send is required */
743 .close
= mpoad_close
,
744 .send
= msg_from_mpoad
747 static struct atm_dev mpc_dev
= {
751 .lock
= __SPIN_LOCK_UNLOCKED(mpc_dev
.lock
)
752 /* members not explicitly initialised will be 0 */
755 static int atm_mpoa_mpoad_attach (struct atm_vcc
*vcc
, int arg
)
757 struct mpoa_client
*mpc
;
758 struct lec_priv
*priv
;
762 init_timer(&mpc_timer
);
765 /* This lets us now how our LECs are doing */
766 err
= register_netdevice_notifier(&mpoa_notifier
);
768 del_timer(&mpc_timer
);
773 mpc
= find_mpc_by_itfnum(arg
);
775 dprintk("mpoa: mpoad_attach: allocating new mpc for itf %d\n", arg
);
780 mpc
->dev
= find_lec_by_itfnum(arg
); /* NULL if there was no lec */
782 if (mpc
->mpoad_vcc
) {
783 printk("mpoa: mpoad_attach: mpoad is already present for itf %d\n", arg
);
787 if (mpc
->dev
) { /* check if the lec is LANE2 capable */
788 priv
= (struct lec_priv
*)mpc
->dev
->priv
;
789 if (priv
->lane_version
< 2) {
793 priv
->lane2_ops
->associate_indicator
= lane2_assoc_ind
;
796 mpc
->mpoad_vcc
= vcc
;
798 vcc_insert_socket(sk_atm(vcc
));
799 set_bit(ATM_VF_META
,&vcc
->flags
);
800 set_bit(ATM_VF_READY
,&vcc
->flags
);
803 char empty
[ATM_ESA_LEN
];
804 memset(empty
, 0, ATM_ESA_LEN
);
806 start_mpc(mpc
, mpc
->dev
);
807 /* set address if mpcd e.g. gets killed and restarted.
808 * If we do not do it now we have to wait for the next LE_ARP
810 if ( memcmp(mpc
->mps_ctrl_addr
, empty
, ATM_ESA_LEN
) != 0 )
811 send_set_mps_ctrl_addr(mpc
->mps_ctrl_addr
, mpc
);
814 __module_get(THIS_MODULE
);
818 static void send_set_mps_ctrl_addr(const char *addr
, struct mpoa_client
*mpc
)
820 struct k_message mesg
;
822 memcpy (mpc
->mps_ctrl_addr
, addr
, ATM_ESA_LEN
);
824 mesg
.type
= SET_MPS_CTRL_ADDR
;
825 memcpy(mesg
.MPS_ctrl
, addr
, ATM_ESA_LEN
);
826 msg_to_mpoad(&mesg
, mpc
);
831 static void mpoad_close(struct atm_vcc
*vcc
)
833 struct mpoa_client
*mpc
;
836 mpc
= find_mpc_by_vcc(vcc
);
838 printk("mpoa: mpoad_close: did not find MPC\n");
841 if (!mpc
->mpoad_vcc
) {
842 printk("mpoa: mpoad_close: close for non-present mpoad\n");
846 mpc
->mpoad_vcc
= NULL
;
848 struct lec_priv
*priv
= (struct lec_priv
*)mpc
->dev
->priv
;
849 priv
->lane2_ops
->associate_indicator
= NULL
;
854 mpc
->in_ops
->destroy_cache(mpc
);
855 mpc
->eg_ops
->destroy_cache(mpc
);
857 while ((skb
= skb_dequeue(&sk_atm(vcc
)->sk_receive_queue
))) {
858 atm_return(vcc
, skb
->truesize
);
862 printk("mpoa: (%s) going down\n",
863 (mpc
->dev
) ? mpc
->dev
->name
: "<unknown>");
864 module_put(THIS_MODULE
);
872 static int msg_from_mpoad(struct atm_vcc
*vcc
, struct sk_buff
*skb
)
875 struct mpoa_client
*mpc
= find_mpc_by_vcc(vcc
);
876 struct k_message
*mesg
= (struct k_message
*)skb
->data
;
877 atomic_sub(skb
->truesize
, &sk_atm(vcc
)->sk_wmem_alloc
);
880 printk("mpoa: msg_from_mpoad: no mpc found\n");
883 dprintk("mpoa: (%s) msg_from_mpoad:", (mpc
->dev
) ? mpc
->dev
->name
: "<unknown>");
885 case MPOA_RES_REPLY_RCVD
:
886 dprintk(" mpoa_res_reply_rcvd\n");
887 MPOA_res_reply_rcvd(mesg
, mpc
);
889 case MPOA_TRIGGER_RCVD
:
890 dprintk(" mpoa_trigger_rcvd\n");
891 MPOA_trigger_rcvd(mesg
, mpc
);
893 case INGRESS_PURGE_RCVD
:
894 dprintk(" nhrp_purge_rcvd\n");
895 ingress_purge_rcvd(mesg
, mpc
);
897 case EGRESS_PURGE_RCVD
:
898 dprintk(" egress_purge_reply_rcvd\n");
899 egress_purge_rcvd(mesg
, mpc
);
902 dprintk(" mps_death\n");
903 mps_death(mesg
, mpc
);
905 case CACHE_IMPOS_RCVD
:
906 dprintk(" cache_impos_rcvd\n");
907 MPOA_cache_impos_rcvd(mesg
, mpc
);
909 case SET_MPC_CTRL_ADDR
:
910 dprintk(" set_mpc_ctrl_addr\n");
911 set_mpc_ctrl_addr_rcvd(mesg
, mpc
);
913 case SET_MPS_MAC_ADDR
:
914 dprintk(" set_mps_mac_addr\n");
915 set_mps_mac_addr_rcvd(mesg
, mpc
);
917 case CLEAN_UP_AND_EXIT
:
918 dprintk(" clean_up_and_exit\n");
919 clean_up(mesg
, mpc
, DIE
);
922 dprintk(" reload\n");
923 clean_up(mesg
, mpc
, RELOAD
);
926 dprintk(" set_mpc_params\n");
927 mpc
->parameters
= mesg
->content
.params
;
930 dprintk(" unknown message %d\n", mesg
->type
);
938 /* Remember that this function may not do things that sleep */
939 int msg_to_mpoad(struct k_message
*mesg
, struct mpoa_client
*mpc
)
944 if (mpc
== NULL
|| !mpc
->mpoad_vcc
) {
945 printk("mpoa: msg_to_mpoad: mesg %d to a non-existent mpoad\n", mesg
->type
);
949 skb
= alloc_skb(sizeof(struct k_message
), GFP_ATOMIC
);
952 skb_put(skb
, sizeof(struct k_message
));
953 skb_copy_to_linear_data(skb
, mesg
, sizeof(*mesg
));
954 atm_force_charge(mpc
->mpoad_vcc
, skb
->truesize
);
956 sk
= sk_atm(mpc
->mpoad_vcc
);
957 skb_queue_tail(&sk
->sk_receive_queue
, skb
);
958 sk
->sk_data_ready(sk
, skb
->len
);
963 static int mpoa_event_listener(struct notifier_block
*mpoa_notifier
, unsigned long event
, void *dev_ptr
)
965 struct net_device
*dev
;
966 struct mpoa_client
*mpc
;
967 struct lec_priv
*priv
;
969 dev
= (struct net_device
*)dev_ptr
;
971 if (!net_eq(dev_net(dev
), &init_net
))
974 if (dev
->name
== NULL
|| strncmp(dev
->name
, "lec", 3))
975 return NOTIFY_DONE
; /* we are only interested in lec:s */
978 case NETDEV_REGISTER
: /* a new lec device was allocated */
979 priv
= (struct lec_priv
*)dev
->priv
;
980 if (priv
->lane_version
< 2)
982 priv
->lane2_ops
->associate_indicator
= lane2_assoc_ind
;
983 mpc
= find_mpc_by_itfnum(priv
->itfnum
);
985 dprintk("mpoa: mpoa_event_listener: allocating new mpc for %s\n",
989 printk("mpoa: mpoa_event_listener: no new mpc");
993 mpc
->dev_num
= priv
->itfnum
;
996 dprintk("mpoa: (%s) was initialized\n", dev
->name
);
998 case NETDEV_UNREGISTER
:
999 /* the lec device was deallocated */
1000 mpc
= find_mpc_by_lec(dev
);
1003 dprintk("mpoa: device (%s) was deallocated\n", dev
->name
);
1009 /* the dev was ifconfig'ed up */
1010 mpc
= find_mpc_by_lec(dev
);
1013 if (mpc
->mpoad_vcc
!= NULL
) {
1014 start_mpc(mpc
, dev
);
1018 /* the dev was ifconfig'ed down */
1019 /* this means that the flow of packets from the
1022 mpc
= find_mpc_by_lec(dev
);
1025 if (mpc
->mpoad_vcc
!= NULL
) {
1031 case NETDEV_CHANGEMTU
:
1032 case NETDEV_CHANGEADDR
:
1033 case NETDEV_GOING_DOWN
:
1043 * Functions which are called after a message is received from mpcd.
1044 * Msg is reused on purpose.
1048 static void MPOA_trigger_rcvd(struct k_message
*msg
, struct mpoa_client
*mpc
)
1050 __be32 dst_ip
= msg
->content
.in_info
.in_dst_ip
;
1051 in_cache_entry
*entry
;
1053 entry
= mpc
->in_ops
->get(dst_ip
, mpc
);
1055 entry
= mpc
->in_ops
->add_entry(dst_ip
, mpc
);
1056 entry
->entry_state
= INGRESS_RESOLVING
;
1057 msg
->type
= SND_MPOA_RES_RQST
;
1058 msg
->content
.in_info
= entry
->ctrl_info
;
1059 msg_to_mpoad(msg
, mpc
);
1060 do_gettimeofday(&(entry
->reply_wait
));
1061 mpc
->in_ops
->put(entry
);
1065 if(entry
->entry_state
== INGRESS_INVALID
){
1066 entry
->entry_state
= INGRESS_RESOLVING
;
1067 msg
->type
= SND_MPOA_RES_RQST
;
1068 msg
->content
.in_info
= entry
->ctrl_info
;
1069 msg_to_mpoad(msg
, mpc
);
1070 do_gettimeofday(&(entry
->reply_wait
));
1071 mpc
->in_ops
->put(entry
);
1075 printk("mpoa: (%s) MPOA_trigger_rcvd: entry already in resolving state\n",
1076 (mpc
->dev
) ? mpc
->dev
->name
: "<unknown>");
1077 mpc
->in_ops
->put(entry
);
1082 * Things get complicated because we have to check if there's an egress
1083 * shortcut with suitable traffic parameters we could use.
1085 static void check_qos_and_open_shortcut(struct k_message
*msg
, struct mpoa_client
*client
, in_cache_entry
*entry
)
1087 __be32 dst_ip
= msg
->content
.in_info
.in_dst_ip
;
1088 struct atm_mpoa_qos
*qos
= atm_mpoa_search_qos(dst_ip
);
1089 eg_cache_entry
*eg_entry
= client
->eg_ops
->get_by_src_ip(dst_ip
, client
);
1091 if(eg_entry
&& eg_entry
->shortcut
){
1092 if(eg_entry
->shortcut
->qos
.txtp
.traffic_class
&
1093 msg
->qos
.txtp
.traffic_class
&
1094 (qos
? qos
->qos
.txtp
.traffic_class
: ATM_UBR
| ATM_CBR
)){
1095 if(eg_entry
->shortcut
->qos
.txtp
.traffic_class
== ATM_UBR
)
1096 entry
->shortcut
= eg_entry
->shortcut
;
1097 else if(eg_entry
->shortcut
->qos
.txtp
.max_pcr
> 0)
1098 entry
->shortcut
= eg_entry
->shortcut
;
1100 if(entry
->shortcut
){
1101 dprintk("mpoa: (%s) using egress SVC to reach %u.%u.%u.%u\n",client
->dev
->name
, NIPQUAD(dst_ip
));
1102 client
->eg_ops
->put(eg_entry
);
1106 if (eg_entry
!= NULL
)
1107 client
->eg_ops
->put(eg_entry
);
1109 /* No luck in the egress cache we must open an ingress SVC */
1110 msg
->type
= OPEN_INGRESS_SVC
;
1111 if (qos
&& (qos
->qos
.txtp
.traffic_class
== msg
->qos
.txtp
.traffic_class
))
1113 msg
->qos
= qos
->qos
;
1114 printk("mpoa: (%s) trying to get a CBR shortcut\n",client
->dev
->name
);
1116 else memset(&msg
->qos
,0,sizeof(struct atm_qos
));
1117 msg_to_mpoad(msg
, client
);
1121 static void MPOA_res_reply_rcvd(struct k_message
*msg
, struct mpoa_client
*mpc
)
1123 __be32 dst_ip
= msg
->content
.in_info
.in_dst_ip
;
1124 in_cache_entry
*entry
= mpc
->in_ops
->get(dst_ip
, mpc
);
1126 dprintk("mpoa: (%s) MPOA_res_reply_rcvd: ip %u.%u.%u.%u\n", mpc
->dev
->name
, NIPQUAD(dst_ip
));
1127 ddprintk("mpoa: (%s) MPOA_res_reply_rcvd() entry = %p", mpc
->dev
->name
, entry
);
1129 printk("\nmpoa: (%s) ARGH, received res. reply for an entry that doesn't exist.\n", mpc
->dev
->name
);
1132 ddprintk(" entry_state = %d ", entry
->entry_state
);
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
);
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
);
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... */
1152 if (entry
->shortcut
!= NULL
) {
1153 printk("mpoa: (%s) MPOA_res_reply_rcvd: entry->shortcut != NULL, impossible!\n",
1155 mpc
->in_ops
->put(entry
);
1159 check_qos_and_open_shortcut(msg
, mpc
, entry
);
1160 entry
->entry_state
= INGRESS_RESOLVED
;
1161 mpc
->in_ops
->put(entry
);
1167 static void ingress_purge_rcvd(struct k_message
*msg
, struct mpoa_client
*mpc
)
1169 __be32 dst_ip
= msg
->content
.in_info
.in_dst_ip
;
1170 __be32 mask
= msg
->ip_mask
;
1171 in_cache_entry
*entry
= mpc
->in_ops
->get_with_mask(dst_ip
, mpc
, mask
);
1174 printk("mpoa: (%s) ingress_purge_rcvd: purge for a non-existing entry, ", mpc
->dev
->name
);
1175 printk("ip = %u.%u.%u.%u\n", NIPQUAD(dst_ip
));
1180 dprintk("mpoa: (%s) ingress_purge_rcvd: removing an ingress entry, ip = %u.%u.%u.%u\n" ,
1181 mpc
->dev
->name
, NIPQUAD(dst_ip
));
1182 write_lock_bh(&mpc
->ingress_lock
);
1183 mpc
->in_ops
->remove_entry(entry
, mpc
);
1184 write_unlock_bh(&mpc
->ingress_lock
);
1185 mpc
->in_ops
->put(entry
);
1186 entry
= mpc
->in_ops
->get_with_mask(dst_ip
, mpc
, mask
);
1187 } while (entry
!= NULL
);
1192 static void egress_purge_rcvd(struct k_message
*msg
, struct mpoa_client
*mpc
)
1194 __be32 cache_id
= msg
->content
.eg_info
.cache_id
;
1195 eg_cache_entry
*entry
= mpc
->eg_ops
->get_by_cache_id(cache_id
, mpc
);
1197 if (entry
== NULL
) {
1198 dprintk("mpoa: (%s) egress_purge_rcvd: purge for a non-existing entry\n", mpc
->dev
->name
);
1202 write_lock_irq(&mpc
->egress_lock
);
1203 mpc
->eg_ops
->remove_entry(entry
, mpc
);
1204 write_unlock_irq(&mpc
->egress_lock
);
1206 mpc
->eg_ops
->put(entry
);
1211 static void purge_egress_shortcut(struct atm_vcc
*vcc
, eg_cache_entry
*entry
)
1214 struct k_message
*purge_msg
;
1215 struct sk_buff
*skb
;
1217 dprintk("mpoa: purge_egress_shortcut: entering\n");
1219 printk("mpoa: purge_egress_shortcut: vcc == NULL\n");
1223 skb
= alloc_skb(sizeof(struct k_message
), GFP_ATOMIC
);
1225 printk("mpoa: purge_egress_shortcut: out of memory\n");
1229 skb_put(skb
, sizeof(struct k_message
));
1230 memset(skb
->data
, 0, sizeof(struct k_message
));
1231 purge_msg
= (struct k_message
*)skb
->data
;
1232 purge_msg
->type
= DATA_PLANE_PURGE
;
1234 purge_msg
->content
.eg_info
= entry
->ctrl_info
;
1236 atm_force_charge(vcc
, skb
->truesize
);
1239 skb_queue_tail(&sk
->sk_receive_queue
, skb
);
1240 sk
->sk_data_ready(sk
, skb
->len
);
1241 dprintk("mpoa: purge_egress_shortcut: exiting:\n");
1247 * Our MPS died. Tell our daemon to send NHRP data plane purge to each
1248 * of the egress shortcuts we have.
1250 static void mps_death( struct k_message
* msg
, struct mpoa_client
* mpc
)
1252 eg_cache_entry
*entry
;
1254 dprintk("mpoa: (%s) mps_death:\n", mpc
->dev
->name
);
1256 if(memcmp(msg
->MPS_ctrl
, mpc
->mps_ctrl_addr
, ATM_ESA_LEN
)){
1257 printk("mpoa: (%s) mps_death: wrong MPS\n", mpc
->dev
->name
);
1261 /* FIXME: This knows too much of the cache structure */
1262 read_lock_irq(&mpc
->egress_lock
);
1263 entry
= mpc
->eg_cache
;
1264 while (entry
!= NULL
) {
1265 purge_egress_shortcut(entry
->shortcut
, entry
);
1266 entry
= entry
->next
;
1268 read_unlock_irq(&mpc
->egress_lock
);
1270 mpc
->in_ops
->destroy_cache(mpc
);
1271 mpc
->eg_ops
->destroy_cache(mpc
);
1276 static void MPOA_cache_impos_rcvd( struct k_message
* msg
, struct mpoa_client
* mpc
)
1278 uint16_t holding_time
;
1279 eg_cache_entry
*entry
= mpc
->eg_ops
->get_by_cache_id(msg
->content
.eg_info
.cache_id
, mpc
);
1281 holding_time
= msg
->content
.eg_info
.holding_time
;
1282 dprintk("mpoa: (%s) MPOA_cache_impos_rcvd: entry = %p, holding_time = %u\n",
1283 mpc
->dev
->name
, entry
, holding_time
);
1284 if(entry
== NULL
&& holding_time
) {
1285 entry
= mpc
->eg_ops
->add_entry(msg
, mpc
);
1286 mpc
->eg_ops
->put(entry
);
1290 mpc
->eg_ops
->update(entry
, holding_time
);
1294 write_lock_irq(&mpc
->egress_lock
);
1295 mpc
->eg_ops
->remove_entry(entry
, mpc
);
1296 write_unlock_irq(&mpc
->egress_lock
);
1298 mpc
->eg_ops
->put(entry
);
1303 static void set_mpc_ctrl_addr_rcvd(struct k_message
*mesg
, struct mpoa_client
*mpc
)
1305 struct lec_priv
*priv
;
1308 uint8_t tlv
[4 + 1 + 1 + 1 + ATM_ESA_LEN
];
1310 tlv
[0] = 00; tlv
[1] = 0xa0; tlv
[2] = 0x3e; tlv
[3] = 0x2a; /* type */
1311 tlv
[4] = 1 + 1 + ATM_ESA_LEN
; /* length */
1312 tlv
[5] = 0x02; /* MPOA client */
1313 tlv
[6] = 0x00; /* number of MPS MAC addresses */
1315 memcpy(&tlv
[7], mesg
->MPS_ctrl
, ATM_ESA_LEN
); /* MPC ctrl ATM addr */
1316 memcpy(mpc
->our_ctrl_addr
, mesg
->MPS_ctrl
, ATM_ESA_LEN
);
1318 dprintk("mpoa: (%s) setting MPC ctrl ATM address to ",
1319 (mpc
->dev
) ? mpc
->dev
->name
: "<unknown>");
1320 for (i
= 7; i
< sizeof(tlv
); i
++)
1321 dprintk("%02x ", tlv
[i
]);
1325 priv
= (struct lec_priv
*)mpc
->dev
->priv
;
1326 retval
= priv
->lane2_ops
->associate_req(mpc
->dev
, mpc
->dev
->dev_addr
, tlv
, sizeof(tlv
));
1328 printk("mpoa: (%s) MPOA device type TLV association failed\n", mpc
->dev
->name
);
1329 retval
= priv
->lane2_ops
->resolve(mpc
->dev
, NULL
, 1, NULL
, NULL
);
1331 printk("mpoa: (%s) targetless LE_ARP request failed\n", mpc
->dev
->name
);
1337 static void set_mps_mac_addr_rcvd(struct k_message
*msg
, struct mpoa_client
*client
)
1340 if(client
->number_of_mps_macs
)
1341 kfree(client
->mps_macs
);
1342 client
->number_of_mps_macs
= 0;
1343 client
->mps_macs
= kmemdup(msg
->MPS_ctrl
, ETH_ALEN
, GFP_KERNEL
);
1344 if (client
->mps_macs
== NULL
) {
1345 printk("mpoa: set_mps_mac_addr_rcvd: out of memory\n");
1348 client
->number_of_mps_macs
= 1;
1354 * purge egress cache and tell daemon to 'action' (DIE, RELOAD)
1356 static void clean_up(struct k_message
*msg
, struct mpoa_client
*mpc
, int action
)
1359 eg_cache_entry
*entry
;
1360 msg
->type
= SND_EGRESS_PURGE
;
1363 /* FIXME: This knows too much of the cache structure */
1364 read_lock_irq(&mpc
->egress_lock
);
1365 entry
= mpc
->eg_cache
;
1366 while (entry
!= NULL
){
1367 msg
->content
.eg_info
= entry
->ctrl_info
;
1368 dprintk("mpoa: cache_id %u\n", entry
->ctrl_info
.cache_id
);
1369 msg_to_mpoad(msg
, mpc
);
1370 entry
= entry
->next
;
1372 read_unlock_irq(&mpc
->egress_lock
);
1375 msg_to_mpoad(msg
, mpc
);
1379 static void mpc_timer_refresh(void)
1381 mpc_timer
.expires
= jiffies
+ (MPC_P2
* HZ
);
1382 mpc_timer
.data
= mpc_timer
.expires
;
1383 mpc_timer
.function
= mpc_cache_check
;
1384 add_timer(&mpc_timer
);
1389 static void mpc_cache_check( unsigned long checking_time
)
1391 struct mpoa_client
*mpc
= mpcs
;
1392 static unsigned long previous_resolving_check_time
;
1393 static unsigned long previous_refresh_time
;
1395 while( mpc
!= NULL
){
1396 mpc
->in_ops
->clear_count(mpc
);
1397 mpc
->eg_ops
->clear_expired(mpc
);
1398 if(checking_time
- previous_resolving_check_time
> mpc
->parameters
.mpc_p4
* HZ
){
1399 mpc
->in_ops
->check_resolving(mpc
);
1400 previous_resolving_check_time
= checking_time
;
1402 if(checking_time
- previous_refresh_time
> mpc
->parameters
.mpc_p5
* HZ
){
1403 mpc
->in_ops
->refresh(mpc
);
1404 previous_refresh_time
= checking_time
;
1408 mpc_timer_refresh();
1413 static int atm_mpoa_ioctl(struct socket
*sock
, unsigned int cmd
, unsigned long arg
)
1416 struct atm_vcc
*vcc
= ATM_SD(sock
);
1418 if (cmd
!= ATMMPC_CTRL
&& cmd
!= ATMMPC_DATA
)
1419 return -ENOIOCTLCMD
;
1421 if (!capable(CAP_NET_ADMIN
))
1426 err
= atm_mpoa_mpoad_attach(vcc
, (int)arg
);
1428 sock
->state
= SS_CONNECTED
;
1431 err
= atm_mpoa_vcc_attach(vcc
, (void __user
*)arg
);
1440 static struct atm_ioctl atm_ioctl_ops
= {
1441 .owner
= THIS_MODULE
,
1442 .ioctl
= atm_mpoa_ioctl
,
1445 static __init
int atm_mpoa_init(void)
1447 register_atm_ioctl(&atm_ioctl_ops
);
1449 if (mpc_proc_init() != 0)
1450 printk(KERN_INFO
"mpoa: failed to initialize /proc/mpoa\n");
1452 printk("mpc.c: " __DATE__
" " __TIME__
" initialized\n");
1457 static void __exit
atm_mpoa_cleanup(void)
1459 struct mpoa_client
*mpc
, *tmp
;
1460 struct atm_mpoa_qos
*qos
, *nextqos
;
1461 struct lec_priv
*priv
;
1465 del_timer(&mpc_timer
);
1466 unregister_netdevice_notifier(&mpoa_notifier
);
1467 deregister_atm_ioctl(&atm_ioctl_ops
);
1471 while (mpc
!= NULL
) {
1473 if (mpc
->dev
!= NULL
) {
1475 priv
= (struct lec_priv
*)mpc
->dev
->priv
;
1476 if (priv
->lane2_ops
!= NULL
)
1477 priv
->lane2_ops
->associate_indicator
= NULL
;
1479 ddprintk("mpoa: cleanup_module: about to clear caches\n");
1480 mpc
->in_ops
->destroy_cache(mpc
);
1481 mpc
->eg_ops
->destroy_cache(mpc
);
1482 ddprintk("mpoa: cleanup_module: caches cleared\n");
1483 kfree(mpc
->mps_macs
);
1484 memset(mpc
, 0, sizeof(struct mpoa_client
));
1485 ddprintk("mpoa: cleanup_module: about to kfree %p\n", mpc
);
1487 ddprintk("mpoa: cleanup_module: next mpc is at %p\n", tmp
);
1493 while (qos
!= NULL
) {
1494 nextqos
= qos
->next
;
1495 dprintk("mpoa: cleanup_module: freeing qos entry %p\n", qos
);
1503 module_init(atm_mpoa_init
);
1504 module_exit(atm_mpoa_cleanup
);
1506 MODULE_LICENSE("GPL");