#include <linux/timer.h>
#include <linux/init.h>
#include <linux/bitops.h>
+#include <linux/capability.h>
+#include <linux/seq_file.h>
/* We are an ethernet device */
#include <linux/if_ether.h>
#include <linux/atmlec.h>
#include <linux/atmmpc.h>
/* Modular too */
-#include <linux/config.h>
#include <linux/module.h>
#include "lec.h"
0
};
-#ifdef CONFIG_PROC_FS
-extern int mpc_proc_init(void);
-extern void mpc_proc_clean(void);
-#endif
-
struct mpoa_client *mpcs = NULL; /* FIXME */
static struct atm_mpoa_qos *qos_head = NULL;
-static struct timer_list mpc_timer = TIMER_INITIALIZER(NULL, 0, 0);
+static DEFINE_TIMER(mpc_timer, NULL, 0, 0);
static struct mpoa_client *find_mpc_by_itfnum(int itf)
/*
* Overwrites the old entry or makes a new one.
*/
-struct atm_mpoa_qos *atm_mpoa_add_qos(uint32_t dst_ip, struct atm_qos *qos)
+struct atm_mpoa_qos *atm_mpoa_add_qos(__be32 dst_ip, struct atm_qos *qos)
{
struct atm_mpoa_qos *entry;
return entry;
}
-struct atm_mpoa_qos *atm_mpoa_search_qos(uint32_t dst_ip)
+struct atm_mpoa_qos *atm_mpoa_search_qos(__be32 dst_ip)
{
struct atm_mpoa_qos *qos;
return 0;
}
-void atm_mpoa_disp_qos(char *page, ssize_t *len)
+/* this is buggered - we need locking for qos_head */
+void atm_mpoa_disp_qos(struct seq_file *m)
{
-
- unsigned char *ip;
- char ipaddr[16];
struct atm_mpoa_qos *qos;
qos = qos_head;
- *len += sprintf(page + *len, "QoS entries for shortcuts:\n");
- *len += sprintf(page + *len, "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");
+ seq_printf(m, "QoS entries for shortcuts:\n");
+ 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");
- ipaddr[sizeof(ipaddr)-1] = '\0';
while (qos != NULL) {
- ip = (unsigned char *)&qos->ipaddr;
- sprintf(ipaddr, "%u.%u.%u.%u", NIPQUAD(ip));
- *len += sprintf(page + *len, "%u.%u.%u.%u\n %-7d %-7d %-7d %-7d %-7d\n %-7d %-7d %-7d %-7d %-7d\n",
- NIPQUAD(ipaddr),
+ seq_printf(m, "%u.%u.%u.%u\n %-7d %-7d %-7d %-7d %-7d\n %-7d %-7d %-7d %-7d %-7d\n",
+ NIPQUAD(qos->ipaddr),
qos->qos.txtp.max_pcr, qos->qos.txtp.pcr, qos->qos.txtp.min_pcr, qos->qos.txtp.max_cdv, qos->qos.txtp.max_sdu,
qos->qos.rxtp.max_pcr, qos->qos.rxtp.pcr, qos->qos.rxtp.min_pcr, qos->qos.rxtp.max_cdv, qos->qos.rxtp.max_sdu);
qos = qos->next;
}
-
- return;
}
static struct net_device *find_lec_by_itfnum(int itf)
{
struct mpoa_client *mpc;
- mpc = kmalloc(sizeof (struct mpoa_client), GFP_KERNEL);
+ mpc = kzalloc(sizeof (struct mpoa_client), GFP_KERNEL);
if (mpc == NULL)
return NULL;
- memset(mpc, 0, sizeof(struct mpoa_client));
- mpc->ingress_lock = RW_LOCK_UNLOCKED;
- mpc->egress_lock = RW_LOCK_UNLOCKED;
+ rwlock_init(&mpc->ingress_lock);
+ rwlock_init(&mpc->egress_lock);
mpc->next = mpcs;
atm_mpoa_init_cache(mpc);
in_cache_entry *entry;
struct iphdr *iph;
char *buff;
- uint32_t ipaddr = 0;
+ __be32 ipaddr = 0;
static struct {
struct llc_snap_hdr hdr;
- uint32_t tag;
+ __be32 tag;
} tagged_llc_snap_hdr = {
{0xaa, 0xaa, 0x03, {0x00, 0x00, 0x00}, {0x88, 0x4c}},
0
memcpy(skb->data, &llc_snap_mpoa_data, sizeof(struct llc_snap_hdr));
}
- atomic_add(skb->truesize, &entry->shortcut->sk->sk_wmem_alloc);
+ atomic_add(skb->truesize, &sk_atm(entry->shortcut)->sk_wmem_alloc);
ATM_SKB(skb)->atm_options = entry->shortcut->atm_options;
entry->shortcut->send(entry->shortcut, skb);
entry->packets_fwded++;
goto non_ip; /* Multi-Protocol Over ATM :-) */
while (i < mpc->number_of_mps_macs) {
- if (memcmp(eth->h_dest, (mpc->mps_macs + i*ETH_ALEN), ETH_ALEN) == 0)
+ if (!compare_ether_addr(eth->h_dest, (mpc->mps_macs + i*ETH_ALEN)))
if ( send_via_shortcut(skb, mpc) == 0 ) /* try shortcut */
return 0; /* success! */
i++;
return retval;
}
-int atm_mpoa_vcc_attach(struct atm_vcc *vcc, long arg)
+static int atm_mpoa_vcc_attach(struct atm_vcc *vcc, void __user *arg)
{
int bytes_left;
struct mpoa_client *mpc;
struct atmmpc_ioc ioc_data;
in_cache_entry *in_entry;
- uint32_t ipaddr;
- unsigned char *ip;
+ __be32 ipaddr;
- bytes_left = copy_from_user(&ioc_data, (void *)arg, sizeof(struct atmmpc_ioc));
+ bytes_left = copy_from_user(&ioc_data, arg, sizeof(struct atmmpc_ioc));
if (bytes_left != 0) {
printk("mpoa: mpc_vcc_attach: Short read (missed %d bytes) from userland\n", bytes_left);
return -EFAULT;
if (in_entry != NULL) mpc->in_ops->put(in_entry);
return -EINVAL;
}
- ip = (unsigned char*)&in_entry->ctrl_info.in_dst_ip;
printk("mpoa: (%s) mpc_vcc_attach: attaching ingress SVC, entry = %u.%u.%u.%u\n",
- mpc->dev->name, ip[0], ip[1], ip[2], ip[3]);
+ mpc->dev->name, NIPQUAD(in_entry->ctrl_info.in_dst_ip));
in_entry->shortcut = vcc;
mpc->in_ops->put(in_entry);
} else {
dprintk("mpoa: (%s) mpc_vcc_close:\n", dev->name);
in_entry = mpc->in_ops->get_by_vcc(vcc, mpc);
if (in_entry) {
- unsigned char *ip __attribute__ ((unused)) =
- (unsigned char *)&in_entry->ctrl_info.in_dst_ip;
dprintk("mpoa: (%s) mpc_vcc_close: ingress SVC closed ip = %u.%u.%u.%u\n",
- mpc->dev->name, ip[0], ip[1], ip[2], ip[3]);
+ mpc->dev->name, NIPQUAD(in_entry->ctrl_info.in_dst_ip));
in_entry->shortcut = NULL;
mpc->in_ops->put(in_entry);
}
struct sk_buff *new_skb;
eg_cache_entry *eg;
struct mpoa_client *mpc;
- uint32_t tag;
+ __be32 tag;
char *tmp;
ddprintk("mpoa: (%s) mpc_push:\n", dev->name);
skb->dev = dev;
if (memcmp(skb->data, &llc_snap_mpoa_ctrl, sizeof(struct llc_snap_hdr)) == 0) {
+ struct sock *sk = sk_atm(vcc);
+
dprintk("mpoa: (%s) mpc_push: control packet arrived\n", dev->name);
/* Pass control packets to daemon */
- skb_queue_tail(&vcc->sk->sk_receive_queue, skb);
- vcc->sk->sk_data_ready(vcc->sk, skb->len);
+ skb_queue_tail(&sk->sk_receive_queue, skb);
+ sk->sk_data_ready(sk, skb->len);
return;
}
}
tmp = skb->data + sizeof(struct llc_snap_hdr);
- tag = *(uint32_t *)tmp;
+ tag = *(__be32 *)tmp;
eg = mpc->eg_ops->get_by_tag(tag, mpc);
if (eg == NULL) {
/* members not explicitly initialised will be 0 */
};
-int atm_mpoa_mpoad_attach (struct atm_vcc *vcc, int arg)
+static int atm_mpoa_mpoad_attach (struct atm_vcc *vcc, int arg)
{
struct mpoa_client *mpc;
struct lec_priv *priv;
+ int err;
if (mpcs == NULL) {
init_timer(&mpc_timer);
mpc_timer_refresh();
/* This lets us now how our LECs are doing */
- register_netdevice_notifier(&mpoa_notifier);
+ err = register_netdevice_notifier(&mpoa_notifier);
+ if (err < 0) {
+ del_timer(&mpc_timer);
+ return err;
+ }
}
mpc = find_mpc_by_itfnum(arg);
mpc->mpoad_vcc = vcc;
vcc->dev = &mpc_dev;
- vcc_insert_socket(vcc->sk);
+ vcc_insert_socket(sk_atm(vcc));
set_bit(ATM_VF_META,&vcc->flags);
set_bit(ATM_VF_READY,&vcc->flags);
mpc->in_ops->destroy_cache(mpc);
mpc->eg_ops->destroy_cache(mpc);
- while ((skb = skb_dequeue(&vcc->sk->sk_receive_queue))) {
+ while ((skb = skb_dequeue(&sk_atm(vcc)->sk_receive_queue))) {
atm_return(vcc, skb->truesize);
kfree_skb(skb);
}
struct mpoa_client *mpc = find_mpc_by_vcc(vcc);
struct k_message *mesg = (struct k_message*)skb->data;
- atomic_sub(skb->truesize, &vcc->sk->sk_wmem_alloc);
+ atomic_sub(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
if (mpc == NULL) {
printk("mpoa: msg_from_mpoad: no mpc found\n");
int msg_to_mpoad(struct k_message *mesg, struct mpoa_client *mpc)
{
struct sk_buff *skb;
+ struct sock *sk;
if (mpc == NULL || !mpc->mpoad_vcc) {
printk("mpoa: msg_to_mpoad: mesg %d to a non-existent mpoad\n", mesg->type);
skb_put(skb, sizeof(struct k_message));
memcpy(skb->data, mesg, sizeof(struct k_message));
atm_force_charge(mpc->mpoad_vcc, skb->truesize);
- skb_queue_tail(&mpc->mpoad_vcc->sk->sk_receive_queue, skb);
- mpc->mpoad_vcc->sk->sk_data_ready(mpc->mpoad_vcc->sk, skb->len);
+
+ sk = sk_atm(mpc->mpoad_vcc);
+ skb_queue_tail(&sk->sk_receive_queue, skb);
+ sk->sk_data_ready(sk, skb->len);
return 0;
}
static void MPOA_trigger_rcvd(struct k_message *msg, struct mpoa_client *mpc)
{
- uint32_t dst_ip = msg->content.in_info.in_dst_ip;
+ __be32 dst_ip = msg->content.in_info.in_dst_ip;
in_cache_entry *entry;
entry = mpc->in_ops->get(dst_ip, mpc);
*/
static void check_qos_and_open_shortcut(struct k_message *msg, struct mpoa_client *client, in_cache_entry *entry)
{
- uint32_t dst_ip = msg->content.in_info.in_dst_ip;
- unsigned char *ip __attribute__ ((unused)) = (unsigned char *)&dst_ip;
+ __be32 dst_ip = msg->content.in_info.in_dst_ip;
struct atm_mpoa_qos *qos = atm_mpoa_search_qos(dst_ip);
eg_cache_entry *eg_entry = client->eg_ops->get_by_src_ip(dst_ip, client);
entry->shortcut = eg_entry->shortcut;
}
if(entry->shortcut){
- dprintk("mpoa: (%s) using egress SVC to reach %u.%u.%u.%u\n",client->dev->name, NIPQUAD(ip));
+ dprintk("mpoa: (%s) using egress SVC to reach %u.%u.%u.%u\n",client->dev->name, NIPQUAD(dst_ip));
client->eg_ops->put(eg_entry);
return;
}
static void MPOA_res_reply_rcvd(struct k_message *msg, struct mpoa_client *mpc)
{
- unsigned char *ip;
-
- uint32_t dst_ip = msg->content.in_info.in_dst_ip;
+ __be32 dst_ip = msg->content.in_info.in_dst_ip;
in_cache_entry *entry = mpc->in_ops->get(dst_ip, mpc);
- ip = (unsigned char *)&dst_ip;
- dprintk("mpoa: (%s) MPOA_res_reply_rcvd: ip %u.%u.%u.%u\n", mpc->dev->name, NIPQUAD(ip));
+
+ dprintk("mpoa: (%s) MPOA_res_reply_rcvd: ip %u.%u.%u.%u\n", mpc->dev->name, NIPQUAD(dst_ip));
ddprintk("mpoa: (%s) MPOA_res_reply_rcvd() entry = %p", mpc->dev->name, entry);
if(entry == NULL){
printk("\nmpoa: (%s) ARGH, received res. reply for an entry that doesn't exist.\n", mpc->dev->name);
static void ingress_purge_rcvd(struct k_message *msg, struct mpoa_client *mpc)
{
- uint32_t dst_ip = msg->content.in_info.in_dst_ip;
- uint32_t mask = msg->ip_mask;
- unsigned char *ip = (unsigned char *)&dst_ip;
+ __be32 dst_ip = msg->content.in_info.in_dst_ip;
+ __be32 mask = msg->ip_mask;
in_cache_entry *entry = mpc->in_ops->get_with_mask(dst_ip, mpc, mask);
if(entry == NULL){
printk("mpoa: (%s) ingress_purge_rcvd: purge for a non-existing entry, ", mpc->dev->name);
- printk("ip = %u.%u.%u.%u\n", ip[0], ip[1], ip[2], ip[3]);
+ printk("ip = %u.%u.%u.%u\n", NIPQUAD(dst_ip));
return;
}
do {
dprintk("mpoa: (%s) ingress_purge_rcvd: removing an ingress entry, ip = %u.%u.%u.%u\n" ,
- mpc->dev->name, ip[0], ip[1], ip[2], ip[3]);
+ mpc->dev->name, NIPQUAD(dst_ip));
write_lock_bh(&mpc->ingress_lock);
mpc->in_ops->remove_entry(entry, mpc);
write_unlock_bh(&mpc->ingress_lock);
static void egress_purge_rcvd(struct k_message *msg, struct mpoa_client *mpc)
{
- uint32_t cache_id = msg->content.eg_info.cache_id;
+ __be32 cache_id = msg->content.eg_info.cache_id;
eg_cache_entry *entry = mpc->eg_ops->get_by_cache_id(cache_id, mpc);
if (entry == NULL) {
static void purge_egress_shortcut(struct atm_vcc *vcc, eg_cache_entry *entry)
{
+ struct sock *sk;
struct k_message *purge_msg;
struct sk_buff *skb;
purge_msg->content.eg_info = entry->ctrl_info;
atm_force_charge(vcc, skb->truesize);
- skb_queue_tail(&vcc->sk->sk_receive_queue, skb);
- vcc->sk->sk_data_ready(vcc->sk, skb->len);
+
+ sk = sk_atm(vcc);
+ skb_queue_tail(&sk->sk_receive_queue, skb);
+ sk->sk_data_ready(sk, skb->len);
dprintk("mpoa: purge_egress_shortcut: exiting:\n");
return;
if(client->number_of_mps_macs)
kfree(client->mps_macs);
client->number_of_mps_macs = 0;
- client->mps_macs = kmalloc(ETH_ALEN,GFP_KERNEL);
+ client->mps_macs = kmemdup(msg->MPS_ctrl, ETH_ALEN, GFP_KERNEL);
if (client->mps_macs == NULL) {
printk("mpoa: set_mps_mac_addr_rcvd: out of memory\n");
return;
}
client->number_of_mps_macs = 1;
- memcpy(client->mps_macs, msg->MPS_ctrl, ETH_ALEN);
return;
}
return;
}
-static void mpc_timer_refresh()
+static void mpc_timer_refresh(void)
{
mpc_timer.expires = jiffies + (MPC_P2 * HZ);
mpc_timer.data = mpc_timer.expires;
sock->state = SS_CONNECTED;
break;
case ATMMPC_DATA:
- err = atm_mpoa_vcc_attach(vcc, arg);
+ err = atm_mpoa_vcc_attach(vcc, (void __user *)arg);
break;
default:
break;
{
register_atm_ioctl(&atm_ioctl_ops);
-#ifdef CONFIG_PROC_FS
if (mpc_proc_init() != 0)
printk(KERN_INFO "mpoa: failed to initialize /proc/mpoa\n");
- else
- printk(KERN_INFO "mpoa: /proc/mpoa initialized\n");
-#endif
printk("mpc.c: " __DATE__ " " __TIME__ " initialized\n");
return 0;
}
-void __exit atm_mpoa_cleanup(void)
+static void __exit atm_mpoa_cleanup(void)
{
struct mpoa_client *mpc, *tmp;
struct atm_mpoa_qos *qos, *nextqos;
struct lec_priv *priv;
-#ifdef CONFIG_PROC_FS
mpc_proc_clean();
-#endif
del_timer(&mpc_timer);
unregister_netdevice_notifier(&mpoa_notifier);