summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-04-28 01:09:25 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-04-28 01:09:25 +0000
commitb9ba7aeb165cffecdffb60aec8c3fa8d590d9ca9 (patch)
tree42d07b0c7246ae2536a702e7c5de9e2732341116 /net
parent7406b0a326f2d70ade2671c37d1beef62249db97 (diff)
Merge with 2.3.99-pre6.
Diffstat (limited to 'net')
-rw-r--r--net/802/tr.c2
-rw-r--r--net/appletalk/ddp.c37
-rw-r--r--net/atm/clip.c20
-rw-r--r--net/atm/common.c6
-rw-r--r--net/atm/common.h5
-rw-r--r--net/atm/lane_mpoa_init.c2
-rw-r--r--net/atm/lec.c14
-rw-r--r--net/atm/lec.h1
-rw-r--r--net/atm/mpc.c1988
-rw-r--r--net/atm/mpoa_caches.c794
-rw-r--r--net/atm/mpoa_caches.h52
-rw-r--r--net/atm/pvc.c34
-rw-r--r--net/atm/raw.c2
-rw-r--r--net/atm/svc.c34
-rw-r--r--net/ax25/af_ax25.c35
-rw-r--r--net/bridge/br.c6
-rw-r--r--net/core/dev.c72
-rw-r--r--net/core/neighbour.c8
-rw-r--r--net/core/netfilter.c14
-rw-r--r--net/core/skbuff.c34
-rw-r--r--net/core/sock.c28
-rw-r--r--net/decnet/af_decnet.c37
-rw-r--r--net/decnet/sysctl_net_decnet.c25
-rw-r--r--net/econet/af_econet.c37
-rw-r--r--net/ipv4/af_inet.c72
-rw-r--r--net/ipv4/arp.c31
-rw-r--r--net/ipv4/fib_rules.c5
-rw-r--r--net/ipv4/icmp.c22
-rw-r--r--net/ipv4/ip_fragment.c9
-rw-r--r--net/ipv4/ip_input.c12
-rw-r--r--net/ipv4/ipconfig.c29
-rw-r--r--net/ipv4/netfilter/ip_conntrack_core.c54
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_generic.c5
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_icmp.c6
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_tcp.c12
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_udp.c6
-rw-r--r--net/ipv4/netfilter/ip_conntrack_standalone.c20
-rw-r--r--net/ipv4/netfilter/ip_nat_standalone.c22
-rw-r--r--net/ipv4/netfilter/ip_queue.c2
-rw-r--r--net/ipv4/netfilter/ip_tables.c24
-rw-r--r--net/ipv4/netfilter/ipchains_core.c14
-rw-r--r--net/ipv4/netfilter/ipfwadm_core.c7
-rw-r--r--net/ipv4/netfilter/ipt_LOG.c15
-rw-r--r--net/ipv4/proc.c10
-rw-r--r--net/ipv4/raw.c36
-rw-r--r--net/ipv4/route.c60
-rw-r--r--net/ipv4/tcp.c30
-rw-r--r--net/ipv4/tcp_input.c15
-rw-r--r--net/ipv4/tcp_ipv4.c44
-rw-r--r--net/ipv4/tcp_output.c23
-rw-r--r--net/ipv4/tcp_timer.c87
-rw-r--r--net/ipv4/udp.c33
-rw-r--r--net/ipv6/af_inet6.c72
-rw-r--r--net/ipv6/proc.c10
-rw-r--r--net/ipv6/raw.c34
-rw-r--r--net/ipv6/tcp_ipv6.c37
-rw-r--r--net/ipv6/udp.c34
-rw-r--r--net/ipx/af_ipx.c34
-rw-r--r--net/ipx/af_spx.c34
-rw-r--r--net/irda/af_irda.c138
-rw-r--r--net/irda/ircomm/ircomm_tty.c2
-rw-r--r--net/netlink/af_netlink.c35
-rw-r--r--net/netrom/af_netrom.c35
-rw-r--r--net/netsyms.c1
-rw-r--r--net/packet/af_packet.c72
-rw-r--r--net/rose/af_rose.c35
-rw-r--r--net/sched/sch_gred.c2
-rw-r--r--net/socket.c17
-rw-r--r--net/sunrpc/Makefile6
-rw-r--r--net/sunrpc/pmap_clnt.c4
-rw-r--r--net/sunrpc/sched.c2
-rw-r--r--net/sunrpc/sunrpc_syms.c3
-rw-r--r--net/sunrpc/svcsock.c12
-rw-r--r--net/sunrpc/sysctl.c2
-rw-r--r--net/unix/af_unix.c71
-rw-r--r--net/x25/af_x25.c41
-rw-r--r--net/x25/x25_facilities.c27
-rw-r--r--net/x25/x25_in.c10
-rw-r--r--net/x25/x25_link.c11
-rw-r--r--net/x25/x25_subr.c10
80 files changed, 2460 insertions, 2323 deletions
diff --git a/net/802/tr.c b/net/802/tr.c
index 4133c2207..316cc6a22 100644
--- a/net/802/tr.c
+++ b/net/802/tr.c
@@ -266,7 +266,7 @@ static void tr_source_route(struct sk_buff *skb,struct trh_hdr *trh,struct net_d
if(entry)
{
#if TR_SR_DEBUG
-printk("source routing for %02X %02X %02X %02X %02X %02X\n",trh->daddr[0],
+printk("source routing for %02X:%02X:%02X:%02X:%02X:%02X\n",trh->daddr[0],
trh->daddr[1],trh->daddr[2],trh->daddr[3],trh->daddr[4],trh->daddr[5]);
#endif
if(!entry->local_ring && (ntohs(entry->rcf) & TR_RCF_LEN_MASK) >> 8)
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
index 9a1b18270..e2012cbb3 100644
--- a/net/appletalk/ddp.c
+++ b/net/appletalk/ddp.c
@@ -292,7 +292,7 @@ static int atalk_get_info(char *buffer, char **start, off_t offset, int length)
if (pos > offset + length) /* We have dumped enough */
break;
}
- spin_lock_bh(&atalk_sockets_lock);
+ spin_unlock_bh(&atalk_sockets_lock);
/* The data in question runs from begin to begin+len */
*start = buffer + (offset - begin); /* Start of wanted data */
@@ -2055,24 +2055,23 @@ static struct net_proto_family atalk_family_ops=
static struct proto_ops SOCKOPS_WRAPPED(atalk_dgram_ops)=
{
- PF_APPLETALK,
-
- atalk_release,
- atalk_bind,
- atalk_connect,
- sock_no_socketpair,
- sock_no_accept,
- atalk_getname,
- datagram_poll,
- atalk_ioctl,
- sock_no_listen,
- sock_no_shutdown,
- sock_no_setsockopt,
- sock_no_getsockopt,
- sock_no_fcntl,
- atalk_sendmsg,
- atalk_recvmsg,
- sock_no_mmap
+ family: PF_APPLETALK,
+
+ release: atalk_release,
+ bind: atalk_bind,
+ connect: atalk_connect,
+ socketpair: sock_no_socketpair,
+ accept: sock_no_accept,
+ getname: atalk_getname,
+ poll: datagram_poll,
+ ioctl: atalk_ioctl,
+ listen: sock_no_listen,
+ shutdown: sock_no_shutdown,
+ setsockopt: sock_no_setsockopt,
+ getsockopt: sock_no_getsockopt,
+ sendmsg: atalk_sendmsg,
+ recvmsg: atalk_recvmsg,
+ mmap: sock_no_mmap,
};
#include <linux/smp_lock.h>
diff --git a/net/atm/clip.c b/net/atm/clip.c
index 37610d6d6..f1bd99b94 100644
--- a/net/atm/clip.c
+++ b/net/atm/clip.c
@@ -172,7 +172,7 @@ static int clip_arp_rcv(struct sk_buff *skb)
DPRINTK("clip_arp_rcv\n");
vcc = ATM_SKB(skb)->vcc;
if (!vcc || !atm_charge(vcc,skb->truesize)) {
- kfree_skb(skb);
+ dev_kfree_skb_any(skb);
return 0;
}
DPRINTK("pushing to %p\n",vcc);
@@ -197,9 +197,8 @@ void clip_push(struct atm_vcc *vcc,struct sk_buff *skb)
atm_return(vcc,skb->truesize);
skb->dev = clip_vcc->entry ? clip_vcc->entry->neigh->dev : clip_devs;
/* clip_vcc->entry == NULL if we don't have an IP address yet */
- skb->rx_dev = NULL;
if (!skb->dev) {
- kfree_skb(skb);
+ dev_kfree_skb_any(skb);
return;
}
ATM_SKB(skb)->vcc = vcc;
@@ -232,18 +231,20 @@ void clip_push(struct atm_vcc *vcc,struct sk_buff *skb)
static void clip_pop(struct atm_vcc *vcc,struct sk_buff *skb)
{
struct clip_vcc *clip_vcc = CLIP_VCC(vcc);
+ struct net_device *dev = skb->dev;
int old;
+ unsigned long flags;
DPRINTK("clip_pop(vcc %p)\n",vcc);
clip_vcc->old_pop(vcc,skb);
/* skb->dev == NULL in outbound ARP packets */
- if (!skb->dev) return;
- spin_lock(&PRIV(skb->dev)->xoff_lock);
+ if (!dev) return;
+ spin_lock_irqsave(&PRIV(dev)->xoff_lock,flags);
if (atm_may_send(vcc,0)) {
old = xchg(&clip_vcc->xoff,0);
- if (old) netif_wake_queue(skb->dev);
+ if (old) netif_wake_queue(dev);
}
- spin_unlock(&PRIV(skb->dev)->xoff_lock);
+ spin_unlock_irqrestore(&PRIV(dev)->xoff_lock,flags);
}
@@ -377,6 +378,7 @@ static int clip_start_xmit(struct sk_buff *skb,struct net_device *dev)
struct atmarp_entry *entry;
struct atm_vcc *vcc;
int old;
+ unsigned long flags;
DPRINTK("clip_start_xmit (skb %p)\n",skb);
if (!skb->dst) {
@@ -439,7 +441,7 @@ return 0;
return 0;
}
if (old) return 0;
- spin_lock(&clip_priv->xoff_lock);
+ spin_lock_irqsave(&clip_priv->xoff_lock,flags);
netif_stop_queue(dev); /* XOFF -> throttle immediately */
barrier();
if (!entry->vccs->xoff)
@@ -448,7 +450,7 @@ return 0;
good enough, because nothing should really be asleep because
of the brief netif_stop_queue. If this isn't true or if it
changes, use netif_wake_queue instead. */
- spin_unlock(&clip_priv->xoff_lock);
+ spin_unlock_irqrestore(&clip_priv->xoff_lock,flags);
return 0;
}
diff --git a/net/atm/common.c b/net/atm/common.c
index 9625061eb..867085ed8 100644
--- a/net/atm/common.c
+++ b/net/atm/common.c
@@ -114,7 +114,6 @@ int atm_create(struct socket *sock,int protocol,int family)
vcc->atm_options = vcc->aal_options = 0;
vcc->timestamp.tv_sec = vcc->timestamp.tv_usec = 0;
init_waitqueue_head(&vcc->sleep);
- init_waitqueue_head(&vcc->wsleep);
skb_queue_head_init(&vcc->recvq);
skb_queue_head_init(&vcc->listenq);
sock->sk = sk;
@@ -412,7 +411,7 @@ int atm_sendmsg(struct socket *sock,struct msghdr *m,int total_len,
if (!size) return 0;
/* verify_area is done by net/socket.c */
eff = (size+3) & ~3; /* align to word boundary */
- add_wait_queue(&vcc->wsleep,&wait);
+ add_wait_queue(&vcc->sleep,&wait);
set_current_state(TASK_INTERRUPTIBLE);
error = 0;
while (!(skb = vcc->alloc_tx(vcc,eff))) {
@@ -437,7 +436,7 @@ int atm_sendmsg(struct socket *sock,struct msghdr *m,int total_len,
}
}
set_current_state(TASK_RUNNING);
- remove_wait_queue(&vcc->wsleep,&wait);
+ remove_wait_queue(&vcc->sleep,&wait);
if (error) return error;
skb->dev = NULL; /* for paths shared with net_device interfaces */
ATM_SKB(skb)->iovcnt = 0;
@@ -459,7 +458,6 @@ unsigned int atm_poll(struct file *file,struct socket *sock,poll_table *wait)
vcc = ATM_SD(sock);
poll_wait(file,&vcc->sleep,wait);
- poll_wait(file,&vcc->wsleep,wait);
mask = 0;
if (skb_peek(&vcc->recvq) || skb_peek(&vcc->listenq))
mask |= POLLIN | POLLRDNORM;
diff --git a/net/atm/common.h b/net/atm/common.h
index cbd2e4edf..faf1866ac 100644
--- a/net/atm/common.h
+++ b/net/atm/common.h
@@ -1,6 +1,6 @@
/* net/atm/common.h - ATM sockets (common part for PVC and SVC) */
-/* Written 1995-1998 by Werner Almesberger, EPFL LRC/ICA */
+/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
#ifndef NET_ATM_COMMON_H
@@ -27,9 +27,6 @@ int atm_getsockopt(struct socket *sock,int level,int optname,char *optval,
int atm_connect_vcc(struct atm_vcc *vcc,int itf,short vpi,int vci);
void atm_release_vcc_sk(struct sock *sk,int free_sk);
int atm_change_qos(struct atm_vcc *vcc,struct atm_qos *qos);
-/* -- now in atmdev.h:
-void atm_async_release_vcc(struct atm_vcc *vcc,int reply);
-*/
void atm_shutdown_dev(struct atm_dev *dev);
int atm_proc_init(void);
diff --git a/net/atm/lane_mpoa_init.c b/net/atm/lane_mpoa_init.c
index 469685703..448826dd2 100644
--- a/net/atm/lane_mpoa_init.c
+++ b/net/atm/lane_mpoa_init.c
@@ -38,12 +38,10 @@ void atm_mpoa_init(void)
#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
-rwlock_t lane_bridge_hook_lock = RW_LOCK_UNLOCKED;
struct net_bridge_fdb_entry *(*br_fdb_get_hook)(struct net_bridge *br,
unsigned char *addr) = NULL;
void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent) = NULL;
#if defined(CONFIG_ATM_LANE_MODULE) || defined(CONFIG_BRIDGE_MODULE)
-EXPORT_SYMBOL(lane_bridge_hook_lock);
EXPORT_SYMBOL(br_fdb_get_hook);
EXPORT_SYMBOL(br_fdb_put_hook);
#endif /* defined(CONFIG_ATM_LANE_MODULE) || defined(CONFIG_BRIDGE_MODULE) */
diff --git a/net/atm/lec.c b/net/atm/lec.c
index 701ece763..96f2877cf 100644
--- a/net/atm/lec.c
+++ b/net/atm/lec.c
@@ -34,7 +34,7 @@
#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
#include <linux/if_bridge.h>
#include "../bridge/br_private.h"
-unsigned char bridge_ula[] = {0x01, 0x80, 0xc2, 0x00, 0x00};
+static unsigned char bridge_ula[] = {0x01, 0x80, 0xc2, 0x00, 0x00};
#endif
/* Modular too */
@@ -472,11 +472,8 @@ lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb)
mesg->content.proxy.mac_addr[2], mesg->content.proxy.mac_addr[3],
mesg->content.proxy.mac_addr[4], mesg->content.proxy.mac_addr[5]);
- read_lock(&lane_bridge_hook_lock);
- if (br_fdb_get_hook == NULL || dev->br_port == NULL) {
- read_unlock(&lane_bridge_hook_lock);
+ if (br_fdb_get_hook == NULL || dev->br_port == NULL)
break;
- }
f = br_fdb_get_hook(dev->br_port->br, mesg->content.proxy.mac_addr);
if (f != NULL &&
@@ -489,7 +486,6 @@ lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb)
skb2 = alloc_skb(sizeof(struct atmlec_msg), GFP_ATOMIC);
if (skb2 == NULL) {
br_fdb_put_hook(f);
- read_unlock(&lane_bridge_hook_lock);
break;
}
skb2->len = sizeof(struct atmlec_msg);
@@ -499,7 +495,6 @@ lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb)
wake_up(&priv->lecd->sleep);
}
if (f != NULL) br_fdb_put_hook(f);
- read_unlock(&lane_bridge_hook_lock);
#endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */
}
break;
@@ -696,7 +691,6 @@ lec_push(struct atm_vcc *vcc, struct sk_buff *skb)
lec_arp_check_empties(priv, vcc, skb);
}
skb->dev = dev;
- skb->rx_dev = NULL;
skb->data += 2; /* skip lec_id */
#ifdef CONFIG_TR
if (priv->is_trdev) skb->protocol = tr_type_trans(skb, dev);
@@ -1079,8 +1073,8 @@ lec_arp_clear_vccs(struct lec_arp_table *entry)
if (entry->recv_vcc) {
entry->recv_vcc->push = entry->old_recv_push;
#if 0
- set_bit(ATM_VF_RELEASED,&entry->vcc->flags);
- clear_bit(ATM_VF_READY,&entry->vcc->flags);
+ set_bit(ATM_VF_RELEASED,&entry->recv_vcc->flags);
+ clear_bit(ATM_VF_READY,&entry->recv_vcc->flags);
entry->recv_vcc->push(entry->recv_vcc, NULL);
#endif
atm_async_release_vcc(entry->recv_vcc, -EPIPE);
diff --git a/net/atm/lec.h b/net/atm/lec.h
index df08e6803..f40a37fa3 100644
--- a/net/atm/lec.h
+++ b/net/atm/lec.h
@@ -16,7 +16,6 @@
#if defined (CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
#include <linux/if_bridge.h>
-extern rwlock_t lane_bridge_hook_lock;
struct net_bridge_fdb_entry *(*br_fdb_get_hook)(struct net_bridge *br,
unsigned char *addr);
void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent);
diff --git a/net/atm/mpc.c b/net/atm/mpc.c
index deeb737f5..1b3e13ad6 100644
--- a/net/atm/mpc.c
+++ b/net/atm/mpc.c
@@ -62,7 +62,7 @@ static void set_mpc_ctrl_addr_rcvd(struct k_message *mesg, struct mpoa_client *m
static void set_mps_mac_addr_rcvd(struct k_message *mesg, struct mpoa_client *mpc);
static uint8_t *copy_macs(struct mpoa_client *mpc, uint8_t *router_mac,
- uint8_t *tlvs, uint8_t mps_macs, uint8_t device_type);
+ uint8_t *tlvs, uint8_t mps_macs, uint8_t device_type);
static void purge_egress_shortcut(struct atm_vcc *vcc, eg_cache_entry *entry);
static void send_set_mps_ctrl_addr(char *addr, struct mpoa_client *mpc);
@@ -76,25 +76,25 @@ static void mpc_timer_refresh(void);
static void mpc_cache_check( unsigned long checking_time );
static struct llc_snap_hdr llc_snap_mpoa_ctrl = {
- 0xaa, 0xaa, 0x03,
- {0x00, 0x00, 0x5e},
- {0x00, 0x03} /* For MPOA control PDUs */
+ 0xaa, 0xaa, 0x03,
+ {0x00, 0x00, 0x5e},
+ {0x00, 0x03} /* For MPOA control PDUs */
};
static struct llc_snap_hdr llc_snap_mpoa_data = {
- 0xaa, 0xaa, 0x03,
- {0x00, 0x00, 0x00},
- {0x08, 0x00} /* This is for IP PDUs only */
+ 0xaa, 0xaa, 0x03,
+ {0x00, 0x00, 0x00},
+ {0x08, 0x00} /* This is for IP PDUs only */
};
static struct llc_snap_hdr llc_snap_mpoa_data_tagged = {
- 0xaa, 0xaa, 0x03,
- {0x00, 0x00, 0x00},
- {0x88, 0x4c} /* This is for tagged data PDUs */
+ 0xaa, 0xaa, 0x03,
+ {0x00, 0x00, 0x00},
+ {0x88, 0x4c} /* This is for tagged data PDUs */
};
static struct notifier_block mpoa_notifier = {
- mpoa_event_listener,
- NULL,
- 0
+ mpoa_event_listener,
+ NULL,
+ 0
};
#ifdef CONFIG_PROC_FS
@@ -109,44 +109,44 @@ static struct timer_list mpc_timer;
static struct mpoa_client *find_mpc_by_itfnum(int itf)
{
- struct mpoa_client *mpc;
-
- mpc = mpcs; /* our global linked list */
- while (mpc != NULL) {
- if (mpc->dev_num == itf)
- return mpc;
- mpc = mpc->next;
- }
-
- return NULL; /* not found */
+ struct mpoa_client *mpc;
+
+ mpc = mpcs; /* our global linked list */
+ while (mpc != NULL) {
+ if (mpc->dev_num == itf)
+ return mpc;
+ mpc = mpc->next;
+ }
+
+ return NULL; /* not found */
}
static struct mpoa_client *find_mpc_by_vcc(struct atm_vcc *vcc)
{
- struct mpoa_client *mpc;
-
- mpc = mpcs; /* our global linked list */
- while (mpc != NULL) {
- if (mpc->mpoad_vcc == vcc)
- return mpc;
- mpc = mpc->next;
- }
-
- return NULL; /* not found */
+ struct mpoa_client *mpc;
+
+ mpc = mpcs; /* our global linked list */
+ while (mpc != NULL) {
+ if (mpc->mpoad_vcc == vcc)
+ return mpc;
+ mpc = mpc->next;
+ }
+
+ return NULL; /* not found */
}
static struct mpoa_client *find_mpc_by_lec(struct net_device *dev)
{
- struct mpoa_client *mpc;
-
- mpc = mpcs; /* our global linked list */
- while (mpc != NULL) {
- if (mpc->dev == dev)
- return mpc;
- mpc = mpc->next;
- }
-
- return NULL; /* not found */
+ struct mpoa_client *mpc;
+
+ mpc = mpcs; /* our global linked list */
+ while (mpc != NULL) {
+ if (mpc->dev == dev)
+ return mpc;
+ mpc = mpc->next;
+ }
+
+ return NULL; /* not found */
}
/*
@@ -158,42 +158,42 @@ static struct mpoa_client *find_mpc_by_lec(struct net_device *dev)
*/
struct atm_mpoa_qos *atm_mpoa_add_qos(uint32_t dst_ip, struct atm_qos *qos)
{
- struct atm_mpoa_qos *entry;
+ struct atm_mpoa_qos *entry;
- entry = atm_mpoa_search_qos(dst_ip);
- if (entry != NULL) {
- entry->qos = *qos;
- return entry;
- }
+ entry = atm_mpoa_search_qos(dst_ip);
+ if (entry != NULL) {
+ entry->qos = *qos;
+ return entry;
+ }
- entry = kmalloc(sizeof(struct atm_qos), GFP_KERNEL);
- if (entry == NULL) {
- printk("mpoa: atm_mpoa_add_qos: out of memory\n");
- return entry;
- }
+ entry = kmalloc(sizeof(struct atm_qos), GFP_KERNEL);
+ if (entry == NULL) {
+ printk("mpoa: atm_mpoa_add_qos: out of memory\n");
+ return entry;
+ }
- entry->ipaddr = dst_ip;
- entry->qos = *qos;
+ entry->ipaddr = dst_ip;
+ entry->qos = *qos;
- entry->next = qos_head;
- qos_head = entry;
+ entry->next = qos_head;
+ qos_head = entry;
- return entry;
+ return entry;
}
struct atm_mpoa_qos *atm_mpoa_search_qos(uint32_t dst_ip)
{
- struct atm_mpoa_qos *qos;
+ struct atm_mpoa_qos *qos;
- qos = qos_head;
- while( qos != NULL ){
- if(qos->ipaddr == dst_ip) {
- break;
+ qos = qos_head;
+ while( qos != NULL ){
+ if(qos->ipaddr == dst_ip) {
+ break;
}
- qos = qos->next;
- }
+ qos = qos->next;
+ }
- return qos;
+ return qos;
}
/*
@@ -202,26 +202,26 @@ struct atm_mpoa_qos *atm_mpoa_search_qos(uint32_t dst_ip)
int atm_mpoa_delete_qos(struct atm_mpoa_qos *entry)
{
- struct atm_mpoa_qos *curr;
-
- if (entry == NULL) return 0;
- if (entry == qos_head) {
- qos_head = qos_head->next;
- kfree(entry);
- return 1;
- }
-
- curr = qos_head;
- while (curr != NULL) {
- if (curr->next == entry) {
- curr->next = entry->next;
- kfree(entry);
- return 1;
- }
- curr = curr->next;
- }
-
- return 0;
+ struct atm_mpoa_qos *curr;
+
+ if (entry == NULL) return 0;
+ if (entry == qos_head) {
+ qos_head = qos_head->next;
+ kfree(entry);
+ return 1;
+ }
+
+ curr = qos_head;
+ while (curr != NULL) {
+ if (curr->next == entry) {
+ curr->next = entry->next;
+ kfree(entry);
+ return 1;
+ }
+ curr = curr->next;
+ }
+
+ return 0;
}
void atm_mpoa_disp_qos(char *page, int *len)
@@ -238,9 +238,9 @@ void atm_mpoa_disp_qos(char *page, int *len)
ipaddr[sizeof(ipaddr)-1] = '\0';
while (qos != NULL) {
ip = (unsigned char *)&qos->ipaddr;
- sprintf(ipaddr, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
- *len += sprintf(page + *len, "%-16s\n %-7d %-7d %-7d %-7d %-7d\n %-7d %-7d %-7d %-7d %-7d\n",
- 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),
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;
@@ -251,28 +251,26 @@ void atm_mpoa_disp_qos(char *page, int *len)
static struct net_device *find_lec_by_itfnum(int itf)
{
- extern struct atm_lane_ops atm_lane_ops; /* in common.c */
-
- if (atm_lane_ops.get_lecs == NULL)
- return NULL;
+ extern struct atm_lane_ops atm_lane_ops; /* in common.c */
+
+ if (atm_lane_ops.get_lecs == NULL)
+ return NULL;
- return atm_lane_ops.get_lecs()[itf]; /* FIXME: something better */
+ return atm_lane_ops.get_lecs()[itf]; /* FIXME: something better */
}
static struct mpoa_client *alloc_mpc(void)
{
- struct mpoa_client *mpc;
-
- mpc = kmalloc(sizeof (struct mpoa_client), GFP_KERNEL);
- if (mpc == NULL)
- return NULL;
- memset(mpc, 0, sizeof(struct mpoa_client));
-#if 0 /* compiler seems to barf on this */
- mpc->ingress_lock = RW_LOCK_UNLOCKED;
- mpc->egress_lock = RW_LOCK_UNLOCKED;
-#endif
- mpc->next = mpcs;
- atm_mpoa_init_cache(mpc);
+ struct mpoa_client *mpc;
+
+ mpc = kmalloc(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;
+ mpc->next = mpcs;
+ atm_mpoa_init_cache(mpc);
mpc->parameters.mpc_p1 = MPC_P1;
mpc->parameters.mpc_p2 = MPC_P2;
@@ -281,9 +279,9 @@ static struct mpoa_client *alloc_mpc(void)
mpc->parameters.mpc_p5 = MPC_P5;
mpc->parameters.mpc_p6 = MPC_P6;
- mpcs = mpc;
+ mpcs = mpc;
- return mpc;
+ return mpc;
}
/*
@@ -295,58 +293,58 @@ static struct mpoa_client *alloc_mpc(void)
*/
static void start_mpc(struct mpoa_client *mpc, struct net_device *dev)
{
-
- dprintk("mpoa: (%s) start_mpc:\n", mpc->dev->name);
- if (dev->hard_start_xmit == NULL) {
- printk("mpoa: (%s) start_mpc: dev->hard_start_xmit == NULL, not starting\n",
- dev->name);
- return;
- }
- mpc->old_hard_start_xmit = dev->hard_start_xmit;
- dev->hard_start_xmit = mpc_send_packet;
-
- return;
+
+ dprintk("mpoa: (%s) start_mpc:\n", mpc->dev->name);
+ if (dev->hard_start_xmit == NULL) {
+ printk("mpoa: (%s) start_mpc: dev->hard_start_xmit == NULL, not starting\n",
+ dev->name);
+ return;
+ }
+ mpc->old_hard_start_xmit = dev->hard_start_xmit;
+ dev->hard_start_xmit = mpc_send_packet;
+
+ return;
}
static void stop_mpc(struct mpoa_client *mpc)
{
-
- dprintk("mpoa: (%s) stop_mpc:", mpc->dev->name);
-
- /* Lets not nullify lec device's dev->hard_start_xmit */
- if (mpc->dev->hard_start_xmit != mpc_send_packet) {
- dprintk(" mpc already stopped, not fatal\n");
- return;
- }
- dprintk("\n");
- mpc->dev->hard_start_xmit = mpc->old_hard_start_xmit;
- mpc->old_hard_start_xmit = NULL;
+
+ dprintk("mpoa: (%s) stop_mpc:", mpc->dev->name);
+
+ /* Lets not nullify lec device's dev->hard_start_xmit */
+ if (mpc->dev->hard_start_xmit != mpc_send_packet) {
+ dprintk(" mpc already stopped, not fatal\n");
+ return;
+ }
+ dprintk("\n");
+ mpc->dev->hard_start_xmit = mpc->old_hard_start_xmit;
+ mpc->old_hard_start_xmit = NULL;
/* close_shortcuts(mpc); ??? FIXME */
-
- return;
+
+ return;
}
static const char * __attribute__ ((unused)) mpoa_device_type_string(char type)
{
- switch(type) {
- case NON_MPOA:
- return "non-MPOA device";
- break;
- case MPS:
- return "MPS";
- break;
- case MPC:
- return "MPC";
- break;
- case MPS_AND_MPC:
- return "both MPS and MPC";
- break;
- default:
- return "unspecified (non-MPOA) device";
- break;
- }
-
- return ""; /* not reached */
+ switch(type) {
+ case NON_MPOA:
+ return "non-MPOA device";
+ break;
+ case MPS:
+ return "MPS";
+ break;
+ case MPC:
+ return "MPC";
+ break;
+ case MPS_AND_MPC:
+ return "both MPS and MPC";
+ break;
+ default:
+ return "unspecified (non-MPOA) device";
+ break;
+ }
+
+ return ""; /* not reached */
}
/*
@@ -363,77 +361,77 @@ static const char * __attribute__ ((unused)) mpoa_device_type_string(char type)
*
*/
static void lane2_assoc_ind(struct net_device *dev, uint8_t *mac_addr,
- uint8_t *tlvs, uint32_t sizeoftlvs)
+ uint8_t *tlvs, uint32_t sizeoftlvs)
{
- uint32_t type;
- uint8_t length, mpoa_device_type, number_of_mps_macs;
- uint8_t *end_of_tlvs;
- struct mpoa_client *mpc;
-
- mpoa_device_type = number_of_mps_macs = 0; /* silence gcc */
- dprintk("mpoa: (%s) lane2_assoc_ind: received TLV(s), ", dev->name);
- dprintk("total length of all TLVs %d\n", sizeoftlvs);
+ uint32_t type;
+ uint8_t length, mpoa_device_type, number_of_mps_macs;
+ uint8_t *end_of_tlvs;
+ struct mpoa_client *mpc;
+
+ mpoa_device_type = number_of_mps_macs = 0; /* silence gcc */
+ dprintk("mpoa: (%s) lane2_assoc_ind: received TLV(s), ", dev->name);
+ dprintk("total length of all TLVs %d\n", sizeoftlvs);
mpc = find_mpc_by_lec(dev); /* Sampo-Fix: moved here from below */
- if (mpc == NULL) {
- printk("mpoa: (%s) lane2_assoc_ind: no mpc\n", dev->name);
- return;
- }
- end_of_tlvs = tlvs + sizeoftlvs;
- while (end_of_tlvs - tlvs >= 5) {
- type = (tlvs[0] << 24) | (tlvs[1] << 16) | (tlvs[2] << 8) | tlvs[3];
- length = tlvs[4];
- tlvs += 5;
- dprintk(" type 0x%x length %02x\n", type, length);
- if (tlvs + length > end_of_tlvs) {
- printk("TLV value extends past its buffer, aborting parse\n");
- return;
- }
-
- if (type == 0) {
- printk("mpoa: (%s) lane2_assoc_ind: TLV type was 0, returning\n", dev->name);
- return;
+ if (mpc == NULL) {
+ printk("mpoa: (%s) lane2_assoc_ind: no mpc\n", dev->name);
+ return;
+ }
+ end_of_tlvs = tlvs + sizeoftlvs;
+ while (end_of_tlvs - tlvs >= 5) {
+ type = (tlvs[0] << 24) | (tlvs[1] << 16) | (tlvs[2] << 8) | tlvs[3];
+ length = tlvs[4];
+ tlvs += 5;
+ dprintk(" type 0x%x length %02x\n", type, length);
+ if (tlvs + length > end_of_tlvs) {
+ printk("TLV value extends past its buffer, aborting parse\n");
+ return;
+ }
+
+ if (type == 0) {
+ printk("mpoa: (%s) lane2_assoc_ind: TLV type was 0, returning\n", dev->name);
+ return;
}
- if (type != TLV_MPOA_DEVICE_TYPE) {
- tlvs += length;
- continue; /* skip other TLVs */
- }
- mpoa_device_type = *tlvs++;
- number_of_mps_macs = *tlvs++;
- dprintk("mpoa: (%s) MPOA device type '%s', ", dev->name, mpoa_device_type_string(mpoa_device_type));
- if (mpoa_device_type == MPS_AND_MPC &&
- length < (42 + number_of_mps_macs*ETH_ALEN)) { /* :) */
- printk("\nmpoa: (%s) lane2_assoc_ind: short MPOA Device Type TLV\n",
- dev->name);
- continue;
- }
- if ((mpoa_device_type == MPS || mpoa_device_type == MPC)
- && length < 22 + number_of_mps_macs*ETH_ALEN) {
- printk("\nmpoa: (%s) lane2_assoc_ind: short MPOA Device Type TLV\n",
- dev->name);
- continue;
- }
- if (mpoa_device_type != MPS && mpoa_device_type != MPS_AND_MPC) {
- dprintk("ignoring non-MPS device\n");
- if (mpoa_device_type == MPC) tlvs += 20;
- continue; /* we are only interested in MPSs */
- }
- if (number_of_mps_macs == 0 && mpoa_device_type == MPS_AND_MPC) {
- printk("\nmpoa: (%s) lane2_assoc_ind: MPS_AND_MPC has zero MACs\n", dev->name);
- continue; /* someone should read the spec */
- }
- dprintk("this MPS has %d MAC addresses\n", number_of_mps_macs);
-
- /* ok, now we can go and tell our daemon the control address of MPS */
- send_set_mps_ctrl_addr(tlvs, mpc);
-
- tlvs = copy_macs(mpc, mac_addr, tlvs, number_of_mps_macs, mpoa_device_type);
- if (tlvs == NULL) return;
- }
- if (end_of_tlvs - tlvs != 0)
- printk("mpoa: (%s) lane2_assoc_ind: ignoring %d bytes of trailing TLV carbage\n",
- dev->name, end_of_tlvs - tlvs);
- return;
+ if (type != TLV_MPOA_DEVICE_TYPE) {
+ tlvs += length;
+ continue; /* skip other TLVs */
+ }
+ mpoa_device_type = *tlvs++;
+ number_of_mps_macs = *tlvs++;
+ dprintk("mpoa: (%s) MPOA device type '%s', ", dev->name, mpoa_device_type_string(mpoa_device_type));
+ if (mpoa_device_type == MPS_AND_MPC &&
+ length < (42 + number_of_mps_macs*ETH_ALEN)) { /* :) */
+ printk("\nmpoa: (%s) lane2_assoc_ind: short MPOA Device Type TLV\n",
+ dev->name);
+ continue;
+ }
+ if ((mpoa_device_type == MPS || mpoa_device_type == MPC)
+ && length < 22 + number_of_mps_macs*ETH_ALEN) {
+ printk("\nmpoa: (%s) lane2_assoc_ind: short MPOA Device Type TLV\n",
+ dev->name);
+ continue;
+ }
+ if (mpoa_device_type != MPS && mpoa_device_type != MPS_AND_MPC) {
+ dprintk("ignoring non-MPS device\n");
+ if (mpoa_device_type == MPC) tlvs += 20;
+ continue; /* we are only interested in MPSs */
+ }
+ if (number_of_mps_macs == 0 && mpoa_device_type == MPS_AND_MPC) {
+ printk("\nmpoa: (%s) lane2_assoc_ind: MPS_AND_MPC has zero MACs\n", dev->name);
+ continue; /* someone should read the spec */
+ }
+ dprintk("this MPS has %d MAC addresses\n", number_of_mps_macs);
+
+ /* ok, now we can go and tell our daemon the control address of MPS */
+ send_set_mps_ctrl_addr(tlvs, mpc);
+
+ tlvs = copy_macs(mpc, mac_addr, tlvs, number_of_mps_macs, mpoa_device_type);
+ if (tlvs == NULL) return;
+ }
+ if (end_of_tlvs - tlvs != 0)
+ printk("mpoa: (%s) lane2_assoc_ind: ignoring %d bytes of trailing TLV carbage\n",
+ dev->name, end_of_tlvs - tlvs);
+ return;
}
/*
@@ -442,91 +440,94 @@ static void lane2_assoc_ind(struct net_device *dev, uint8_t *mac_addr,
* For a freshly allocated MPOA client mpc->mps_macs == 0.
*/
static uint8_t *copy_macs(struct mpoa_client *mpc, uint8_t *router_mac,
- uint8_t *tlvs, uint8_t mps_macs, uint8_t device_type)
+ uint8_t *tlvs, uint8_t mps_macs, uint8_t device_type)
{
- int num_macs;
- num_macs = (mps_macs > 1) ? mps_macs : 1;
-
- if (mpc->number_of_mps_macs != num_macs) { /* need to reallocate? */
- if (mpc->number_of_mps_macs != 0) kfree(mpc->mps_macs);
- mpc->number_of_mps_macs = 0;
- mpc->mps_macs = kmalloc(num_macs*ETH_ALEN, GFP_KERNEL);
- if (mpc->mps_macs == NULL) {
- printk("mpoa: (%s) copy_macs: out of mem\n", mpc->dev->name);
- return NULL;
- }
- }
- memcpy(mpc->mps_macs, router_mac, ETH_ALEN);
- tlvs += 20; if (device_type == MPS_AND_MPC) tlvs += 20;
- if (mps_macs > 0)
- memcpy(mpc->mps_macs, tlvs, mps_macs*ETH_ALEN);
- tlvs += mps_macs*ETH_ALEN;
- mpc->number_of_mps_macs = num_macs;
-
- return tlvs;
+ int num_macs;
+ num_macs = (mps_macs > 1) ? mps_macs : 1;
+
+ if (mpc->number_of_mps_macs != num_macs) { /* need to reallocate? */
+ if (mpc->number_of_mps_macs != 0) kfree(mpc->mps_macs);
+ mpc->number_of_mps_macs = 0;
+ mpc->mps_macs = kmalloc(num_macs*ETH_ALEN, GFP_KERNEL);
+ if (mpc->mps_macs == NULL) {
+ printk("mpoa: (%s) copy_macs: out of mem\n", mpc->dev->name);
+ return NULL;
+ }
+ }
+ memcpy(mpc->mps_macs, router_mac, ETH_ALEN);
+ tlvs += 20; if (device_type == MPS_AND_MPC) tlvs += 20;
+ if (mps_macs > 0)
+ memcpy(mpc->mps_macs, tlvs, mps_macs*ETH_ALEN);
+ tlvs += mps_macs*ETH_ALEN;
+ mpc->number_of_mps_macs = num_macs;
+
+ return tlvs;
}
-/* FIXME: tarvitsee työtä */
static int send_via_shortcut(struct sk_buff *skb, struct mpoa_client *mpc)
{
- in_cache_entry *entry;
- struct iphdr *iph;
- char *buff;
- uint32_t ipaddr = 0;
-
- static struct {
- struct llc_snap_hdr hdr;
- uint32_t tag;
- } tagged_llc_snap_hdr = {
- {0xaa, 0xaa, 0x03, {0x00, 0x00, 0x00}, {0x88, 0x4c}},
- 0
- };
-
- buff = skb->data + mpc->dev->hard_header_len;
- iph = (struct iphdr *)buff;
+ in_cache_entry *entry;
+ struct iphdr *iph;
+ char *buff;
+ uint32_t ipaddr = 0;
+
+ static struct {
+ struct llc_snap_hdr hdr;
+ uint32_t tag;
+ } tagged_llc_snap_hdr = {
+ {0xaa, 0xaa, 0x03, {0x00, 0x00, 0x00}, {0x88, 0x4c}},
+ 0
+ };
+
+ buff = skb->data + mpc->dev->hard_header_len;
+ iph = (struct iphdr *)buff;
ipaddr = iph->daddr;
- ddprintk("mpoa: (%s) send_via_shortcut: ipaddr 0x%x\n", mpc->dev->name, ipaddr);
-
- entry = mpc->in_ops->search(ipaddr, mpc);
- if (entry == NULL) {
- mpc->in_ops->new_entry(ipaddr, mpc);
- return 1;
- }
- if (mpc->in_ops->cache_hit(entry, mpc) != OPEN){ /* threshold not exceeded or VCC not ready */
- ddprintk("mpoa: (%s) send_via_shortcut: cache_hit: returns != OPEN\n", mpc->dev->name);
- return 1;
- }
-
- ddprintk("mpoa: (%s) send_via_shortcut: using shortcut\n", mpc->dev->name);
- /* MPOA spec A.1.4, MPOA client must decrement IP ttl at least by one */
- if (iph->ttl <= 1) {
- ddprintk("mpoa: (%s) send_via_shortcut: IP ttl = %u, using LANE\n", mpc->dev->name, iph->ttl);
- return 1;
- }
- iph->ttl--;
- iph->check = 0;
- iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
-
- if (entry->ctrl_info.tag != 0) {
- ddprintk("mpoa: (%s) send_via_shortcut: adding tag 0x%x\n", mpc->dev->name, entry->ctrl_info.tag);
- tagged_llc_snap_hdr.tag = entry->ctrl_info.tag;
- skb_pull(skb, ETH_HLEN); /* get rid of Eth header */
- skb_push(skb, sizeof(tagged_llc_snap_hdr)); /* add LLC/SNAP header */
- memcpy(skb->data, &tagged_llc_snap_hdr, sizeof(tagged_llc_snap_hdr));
- } else {
- skb_pull(skb, ETH_HLEN); /* get rid of Eth header */
- skb_push(skb, sizeof(struct llc_snap_hdr)); /* add LLC/SNAP header + tag */
- memcpy(skb->data, &llc_snap_mpoa_data, sizeof(struct llc_snap_hdr));
- }
-
- atomic_add(skb->truesize, &entry->shortcut->tx_inuse);
+ ddprintk("mpoa: (%s) send_via_shortcut: ipaddr 0x%x\n", mpc->dev->name, ipaddr);
+
+ entry = mpc->in_ops->get(ipaddr, mpc);
+ if (entry == NULL) {
+ entry = mpc->in_ops->add_entry(ipaddr, mpc);
+ if (entry != NULL) mpc->in_ops->put(entry);
+ return 1;
+ }
+ if (mpc->in_ops->cache_hit(entry, mpc) != OPEN){ /* threshold not exceeded or VCC not ready */
+ ddprintk("mpoa: (%s) send_via_shortcut: cache_hit: returns != OPEN\n", mpc->dev->name);
+ mpc->in_ops->put(entry);
+ return 1;
+ }
+
+ ddprintk("mpoa: (%s) send_via_shortcut: using shortcut\n", mpc->dev->name);
+ /* MPOA spec A.1.4, MPOA client must decrement IP ttl at least by one */
+ if (iph->ttl <= 1) {
+ ddprintk("mpoa: (%s) send_via_shortcut: IP ttl = %u, using LANE\n", mpc->dev->name, iph->ttl);
+ mpc->in_ops->put(entry);
+ return 1;
+ }
+ iph->ttl--;
+ iph->check = 0;
+ iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
+
+ if (entry->ctrl_info.tag != 0) {
+ ddprintk("mpoa: (%s) send_via_shortcut: adding tag 0x%x\n", mpc->dev->name, entry->ctrl_info.tag);
+ tagged_llc_snap_hdr.tag = entry->ctrl_info.tag;
+ skb_pull(skb, ETH_HLEN); /* get rid of Eth header */
+ skb_push(skb, sizeof(tagged_llc_snap_hdr)); /* add LLC/SNAP header */
+ memcpy(skb->data, &tagged_llc_snap_hdr, sizeof(tagged_llc_snap_hdr));
+ } else {
+ skb_pull(skb, ETH_HLEN); /* get rid of Eth header */
+ skb_push(skb, sizeof(struct llc_snap_hdr)); /* add LLC/SNAP header + tag */
+ memcpy(skb->data, &llc_snap_mpoa_data, sizeof(struct llc_snap_hdr));
+ }
+
+ atomic_add(skb->truesize, &entry->shortcut->tx_inuse);
ATM_SKB(skb)->iovcnt = 0; /* just to be safe ... */
ATM_SKB(skb)->atm_options = entry->shortcut->atm_options;
- entry->shortcut->send(entry->shortcut, skb);
+ entry->shortcut->send(entry->shortcut, skb);
entry->packets_fwded++;
+ mpc->in_ops->put(entry);
- return 0;
+ return 0;
}
/*
@@ -534,75 +535,77 @@ static int send_via_shortcut(struct sk_buff *skb, struct mpoa_client *mpc)
*/
static int mpc_send_packet(struct sk_buff *skb, struct net_device *dev)
{
- int retval;
- struct mpoa_client *mpc;
- struct ethhdr *eth;
- int i = 0;
-
- mpc = find_mpc_by_lec(dev); /* this should NEVER fail */
- if(mpc == NULL) {
- printk("mpoa: (%s) mpc_send_packet: no MPC found\n", dev->name);
- goto non_ip;
- }
-
- eth = (struct ethhdr *)skb->data;
- if (eth->h_proto != htons(ETH_P_IP))
- 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 ( send_via_shortcut(skb, mpc) == 0 ) /* try shortcut */
- return 0; /* success! */
- i++;
- }
+ int retval;
+ struct mpoa_client *mpc;
+ struct ethhdr *eth;
+ int i = 0;
+
+ mpc = find_mpc_by_lec(dev); /* this should NEVER fail */
+ if(mpc == NULL) {
+ printk("mpoa: (%s) mpc_send_packet: no MPC found\n", dev->name);
+ goto non_ip;
+ }
+
+ eth = (struct ethhdr *)skb->data;
+ if (eth->h_proto != htons(ETH_P_IP))
+ 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 ( send_via_shortcut(skb, mpc) == 0 ) /* try shortcut */
+ return 0; /* success! */
+ i++;
+ }
non_ip:
- retval = mpc->old_hard_start_xmit(skb,dev);
-
- return retval;
+ retval = mpc->old_hard_start_xmit(skb,dev);
+
+ return retval;
}
int atm_mpoa_vcc_attach(struct atm_vcc *vcc, long arg)
{
- int bytes_left;
- struct mpoa_client *mpc;
- struct atmmpc_ioc ioc_data;
- in_cache_entry *in_entry;
- uint32_t ipaddr;
+ int bytes_left;
+ struct mpoa_client *mpc;
+ struct atmmpc_ioc ioc_data;
+ in_cache_entry *in_entry;
+ uint32_t ipaddr;
unsigned char *ip;
- bytes_left = copy_from_user(&ioc_data, (void *)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;
- }
- ipaddr = ioc_data.ipaddr;
- if (ioc_data.dev_num < 0 || ioc_data.dev_num >= MAX_LEC_ITF)
- return -EINVAL;
-
- mpc = find_mpc_by_itfnum(ioc_data.dev_num);
- if (mpc == NULL)
- return -EINVAL;
-
- if (ioc_data.type == MPC_SOCKET_INGRESS) {
- in_entry = mpc->in_ops->search(ipaddr, mpc);
- if (in_entry == NULL || in_entry->entry_state < INGRESS_RESOLVED) {
- printk("mpoa: (%s) mpc_vcc_attach: did not find RESOLVED entry from ingress cache\n",
- mpc->dev->name);
- return -EINVAL;
- }
+ bytes_left = copy_from_user(&ioc_data, (void *)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;
+ }
+ ipaddr = ioc_data.ipaddr;
+ if (ioc_data.dev_num < 0 || ioc_data.dev_num >= MAX_LEC_ITF)
+ return -EINVAL;
+
+ mpc = find_mpc_by_itfnum(ioc_data.dev_num);
+ if (mpc == NULL)
+ return -EINVAL;
+
+ if (ioc_data.type == MPC_SOCKET_INGRESS) {
+ in_entry = mpc->in_ops->get(ipaddr, mpc);
+ if (in_entry == NULL || in_entry->entry_state < INGRESS_RESOLVED) {
+ printk("mpoa: (%s) mpc_vcc_attach: did not find RESOLVED entry from ingress cache\n",
+ mpc->dev->name);
+ 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]);
- in_entry->shortcut = vcc;
- } else {
- printk("mpoa: (%s) mpc_vcc_attach: attaching egress SVC\n", mpc->dev->name);
- }
-
- vcc->proto_data = mpc->dev;
- vcc->push = mpc_push;
-
- return 0;
+ 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]);
+ in_entry->shortcut = vcc;
+ mpc->in_ops->put(in_entry);
+ } else {
+ printk("mpoa: (%s) mpc_vcc_attach: attaching egress SVC\n", mpc->dev->name);
+ }
+
+ vcc->proto_data = mpc->dev;
+ vcc->push = mpc_push;
+
+ return 0;
}
/*
@@ -610,251 +613,250 @@ int atm_mpoa_vcc_attach(struct atm_vcc *vcc, long arg)
*/
static void mpc_vcc_close(struct atm_vcc *vcc, struct net_device *dev)
{
- struct mpoa_client *mpc;
- in_cache_entry *in_entry;
- eg_cache_entry *eg_entry;
-
- mpc = find_mpc_by_lec(dev);
- if (mpc == NULL) {
- printk("mpoa: (%s) mpc_vcc_close: close for unknown MPC\n", dev->name);
- return;
- }
-
- dprintk("mpoa: (%s) mpc_vcc_close:\n", dev->name);
- in_entry = mpc->in_ops->search_by_vcc(vcc, mpc);
- if (in_entry) {
- unsigned char *ip __attribute__ ((unused)) =
+ struct mpoa_client *mpc;
+ in_cache_entry *in_entry;
+ eg_cache_entry *eg_entry;
+
+ mpc = find_mpc_by_lec(dev);
+ if (mpc == NULL) {
+ printk("mpoa: (%s) mpc_vcc_close: close for unknown MPC\n", dev->name);
+ return;
+ }
+
+ 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]);
- in_entry->shortcut = NULL;
- }
- eg_entry = mpc->eg_ops->search_by_vcc(vcc, mpc);
- if (eg_entry) {
- dprintk("mpoa: (%s) mpc_vcc_close: egress SVC closed\n", mpc->dev->name);
- eg_entry->shortcut = NULL;
- }
-
- if (in_entry == NULL && eg_entry == NULL)
- dprintk("mpoa: (%s) mpc_vcc_close: unused vcc closed\n", dev->name);
-
- return;
+ 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]);
+ in_entry->shortcut = NULL;
+ mpc->in_ops->put(in_entry);
+ }
+ eg_entry = mpc->eg_ops->get_by_vcc(vcc, mpc);
+ if (eg_entry) {
+ dprintk("mpoa: (%s) mpc_vcc_close: egress SVC closed\n", mpc->dev->name);
+ eg_entry->shortcut = NULL;
+ mpc->eg_ops->put(eg_entry);
+ }
+
+ if (in_entry == NULL && eg_entry == NULL)
+ dprintk("mpoa: (%s) mpc_vcc_close: unused vcc closed\n", dev->name);
+
+ return;
}
static void mpc_push(struct atm_vcc *vcc, struct sk_buff *skb)
{
- struct net_device *dev = (struct net_device *)vcc->proto_data;
- struct sk_buff *new_skb;
- eg_cache_entry *eg;
- struct mpoa_client *mpc;
+ struct net_device *dev = (struct net_device *)vcc->proto_data;
+ struct sk_buff *new_skb;
+ eg_cache_entry *eg;
+ struct mpoa_client *mpc;
uint32_t tag;
- char *tmp;
-
- ddprintk("mpoa: (%s) mpc_push:\n", dev->name);
- if (skb == NULL) {
- dprintk("mpoa: (%s) mpc_push: null skb, closing VCC\n", dev->name);
- mpc_vcc_close(vcc, dev);
- return;
- }
-
- skb->dev = dev;
- if (memcmp(skb->data, &llc_snap_mpoa_ctrl, sizeof(struct llc_snap_hdr)) == 0) {
- dprintk("mpoa: (%s) mpc_push: control packet arrived\n", dev->name);
- skb_queue_tail(&vcc->recvq, skb); /* Pass control packets to daemon */
- wake_up(&vcc->sleep);
- return;
- }
-
- /* data coming over the shortcut */
- atm_return(vcc, skb->truesize);
+ char *tmp;
+
+ ddprintk("mpoa: (%s) mpc_push:\n", dev->name);
+ if (skb == NULL) {
+ dprintk("mpoa: (%s) mpc_push: null skb, closing VCC\n", dev->name);
+ mpc_vcc_close(vcc, dev);
+ return;
+ }
+
+ skb->dev = dev;
+ if (memcmp(skb->data, &llc_snap_mpoa_ctrl, sizeof(struct llc_snap_hdr)) == 0) {
+ dprintk("mpoa: (%s) mpc_push: control packet arrived\n", dev->name);
+ skb_queue_tail(&vcc->recvq, skb); /* Pass control packets to daemon */
+ wake_up(&vcc->sleep);
+ return;
+ }
+
+ /* data coming over the shortcut */
+ atm_return(vcc, skb->truesize);
mpc = find_mpc_by_lec(dev);
- if (mpc == NULL) {
- printk("mpoa: (%s) mpc_push: unknown MPC\n", dev->name);
- return;
- }
+ if (mpc == NULL) {
+ printk("mpoa: (%s) mpc_push: unknown MPC\n", dev->name);
+ return;
+ }
- if (memcmp(skb->data, &llc_snap_mpoa_data_tagged, sizeof(struct llc_snap_hdr)) == 0) { /* MPOA tagged data */
- ddprintk("mpoa: (%s) mpc_push: tagged data packet arrived\n", dev->name);
+ if (memcmp(skb->data, &llc_snap_mpoa_data_tagged, sizeof(struct llc_snap_hdr)) == 0) { /* MPOA tagged data */
+ ddprintk("mpoa: (%s) mpc_push: tagged data packet arrived\n", dev->name);
- } else if (memcmp(skb->data, &llc_snap_mpoa_data, sizeof(struct llc_snap_hdr)) == 0) { /* MPOA data */
- printk("mpoa: (%s) mpc_push: non-tagged data packet arrived\n", dev->name);
- printk(" mpc_push: non-tagged data unsupported, purging\n");
- kfree_skb(skb);
- return;
- } else {
- printk("mpoa: (%s) mpc_push: garbage arrived, purging\n", dev->name);
- kfree_skb(skb);
- return;
- }
-
- tmp = skb->data + sizeof(struct llc_snap_hdr);
- tag = *(uint32_t *)tmp;
-
- eg = mpc->eg_ops->search_by_tag(tag, mpc);
- if (eg == NULL) {
- printk("mpoa: (%s) mpc_push: Didn't find egress cache entry, tag = %u\n",
- dev->name,tag);
- purge_egress_shortcut(vcc, NULL);
- kfree_skb(skb);
- return;
- }
-
- /*
- * See if ingress MPC is using shortcut we opened as a return channel.
- * This means we have a bi-directional vcc opened by us.
- */
- if (eg->shortcut == NULL) {
- eg->shortcut = vcc;
- printk("mpoa: (%s) mpc_push: egress SVC in use\n", dev->name);
- }
-
- skb_pull(skb, sizeof(struct llc_snap_hdr) + sizeof(tag)); /* get rid of LLC/SNAP header */
- new_skb = skb_realloc_headroom(skb, eg->ctrl_info.DH_length); /* LLC/SNAP is shorter than MAC header :( */
- kfree_skb(skb);
- if (new_skb == NULL) return;
- skb_push(new_skb, eg->ctrl_info.DH_length); /* add MAC header */
- memcpy(new_skb->data, eg->ctrl_info.DLL_header, eg->ctrl_info.DH_length);
- new_skb->protocol = eth_type_trans(new_skb, dev);
- new_skb->nh.raw = new_skb->data;
+ } else if (memcmp(skb->data, &llc_snap_mpoa_data, sizeof(struct llc_snap_hdr)) == 0) { /* MPOA data */
+ printk("mpoa: (%s) mpc_push: non-tagged data packet arrived\n", dev->name);
+ printk(" mpc_push: non-tagged data unsupported, purging\n");
+ dev_kfree_skb_any(skb);
+ return;
+ } else {
+ printk("mpoa: (%s) mpc_push: garbage arrived, purging\n", dev->name);
+ dev_kfree_skb_any(skb);
+ return;
+ }
+
+ tmp = skb->data + sizeof(struct llc_snap_hdr);
+ tag = *(uint32_t *)tmp;
+
+ eg = mpc->eg_ops->get_by_tag(tag, mpc);
+ if (eg == NULL) {
+ printk("mpoa: (%s) mpc_push: Didn't find egress cache entry, tag = %u\n",
+ dev->name,tag);
+ purge_egress_shortcut(vcc, NULL);
+ dev_kfree_skb_any(skb);
+ return;
+ }
+
+ /*
+ * See if ingress MPC is using shortcut we opened as a return channel.
+ * This means we have a bi-directional vcc opened by us.
+ */
+ if (eg->shortcut == NULL) {
+ eg->shortcut = vcc;
+ printk("mpoa: (%s) mpc_push: egress SVC in use\n", dev->name);
+ }
+
+ skb_pull(skb, sizeof(struct llc_snap_hdr) + sizeof(tag)); /* get rid of LLC/SNAP header */
+ new_skb = skb_realloc_headroom(skb, eg->ctrl_info.DH_length); /* LLC/SNAP is shorter than MAC header :( */
+ dev_kfree_skb_any(skb);
+ if (new_skb == NULL){
+ mpc->eg_ops->put(eg);
+ return;
+ }
+ skb_push(new_skb, eg->ctrl_info.DH_length); /* add MAC header */
+ memcpy(new_skb->data, eg->ctrl_info.DLL_header, eg->ctrl_info.DH_length);
+ new_skb->protocol = eth_type_trans(new_skb, dev);
+ new_skb->nh.raw = new_skb->data;
eg->latest_ip_addr = new_skb->nh.iph->saddr;
- eg->packets_rcvd++;
-
- netif_rx(new_skb);
+ eg->packets_rcvd++;
+ mpc->eg_ops->put(eg);
+
+ netif_rx(new_skb);
- return;
+ return;
}
static struct atmdev_ops mpc_ops = { /* only send is required */
- close: mpoad_close,
- send: msg_from_mpoad
+ close: mpoad_close,
+ send: msg_from_mpoad
};
static struct atm_dev mpc_dev = {
- &mpc_ops, /* device operations */
- NULL, /* PHY operations */
- "mpc", /* device type name */
- 42, /* device index (dummy) */
- NULL, /* VCC table */
- NULL, /* last VCC */
- NULL, /* per-device data */
- NULL, /* private PHY data */
- { 0 }, /* device flags */
- NULL, /* local ATM address */
- { 0 } /* no ESI */
- /* rest of the members will be 0 */
+ &mpc_ops, /* device operations */
+ NULL, /* PHY operations */
+ "mpc", /* device type name */
+ 42, /* device index (dummy) */
+ NULL, /* VCC table */
+ NULL, /* last VCC */
+ NULL, /* per-device data */
+ NULL, /* private PHY data */
+ { 0 }, /* device flags */
+ NULL, /* local ATM address */
+ { 0 } /* no ESI */
+ /* rest of the members will be 0 */
};
int atm_mpoa_mpoad_attach (struct atm_vcc *vcc, int arg)
{
- struct mpoa_client *mpc;
- struct lec_priv *priv;
-
- if (mpcs == NULL) {
- init_timer(&mpc_timer);
- mpc_timer_refresh();
-
- /* This lets us now how our LECs are doing */
- register_netdevice_notifier(&mpoa_notifier);
- }
-
- mpc = find_mpc_by_itfnum(arg);
- if (mpc == NULL) {
- dprintk("mpoa: mpoad_attach: allocating new mpc for itf %d\n", arg);
- mpc = alloc_mpc();
- mpc->dev_num = arg;
- mpc->dev = find_lec_by_itfnum(arg); /* NULL if there was no lec */
- }
- if (mpc->mpoad_vcc) {
- printk("mpoa: mpoad_attach: mpoad is already present for itf %d\n", arg);
- return -EADDRINUSE;
- }
-
- if (mpc->dev) { /* check if the lec is LANE2 capable */
- priv = (struct lec_priv *)mpc->dev->priv;
- if (priv->lane_version < 2)
- mpc->dev = NULL;
+ struct mpoa_client *mpc;
+ struct lec_priv *priv;
+
+ if (mpcs == NULL) {
+ init_timer(&mpc_timer);
+ mpc_timer_refresh();
+
+ /* This lets us now how our LECs are doing */
+ register_netdevice_notifier(&mpoa_notifier);
+ }
+
+ mpc = find_mpc_by_itfnum(arg);
+ if (mpc == NULL) {
+ dprintk("mpoa: mpoad_attach: allocating new mpc for itf %d\n", arg);
+ mpc = alloc_mpc();
+ mpc->dev_num = arg;
+ mpc->dev = find_lec_by_itfnum(arg); /* NULL if there was no lec */
+ }
+ if (mpc->mpoad_vcc) {
+ printk("mpoa: mpoad_attach: mpoad is already present for itf %d\n", arg);
+ return -EADDRINUSE;
+ }
+
+ if (mpc->dev) { /* check if the lec is LANE2 capable */
+ priv = (struct lec_priv *)mpc->dev->priv;
+ if (priv->lane_version < 2)
+ mpc->dev = NULL;
else
- priv->lane2_ops->associate_indicator = lane2_assoc_ind;
- }
+ priv->lane2_ops->associate_indicator = lane2_assoc_ind;
+ }
- mpc->mpoad_vcc = vcc;
- bind_vcc(vcc, &mpc_dev);
+ mpc->mpoad_vcc = vcc;
+ bind_vcc(vcc, &mpc_dev);
set_bit(ATM_VF_META,&vcc->flags);
set_bit(ATM_VF_READY,&vcc->flags);
- if (mpc->dev) {
- char empty[ATM_ESA_LEN];
- memset(empty, 0, ATM_ESA_LEN);
-
- start_mpc(mpc, mpc->dev);
- /* set address if mpcd e.g. gets killed and restarted.
- * If we do not do it now we have to wait for the next LE_ARP
- */
- if ( memcmp(mpc->mps_ctrl_addr, empty, ATM_ESA_LEN) != 0 )
- send_set_mps_ctrl_addr(mpc->mps_ctrl_addr, mpc);
- }
-
- MOD_INC_USE_COUNT;
- return arg;
+ if (mpc->dev) {
+ char empty[ATM_ESA_LEN];
+ memset(empty, 0, ATM_ESA_LEN);
+
+ start_mpc(mpc, mpc->dev);
+ /* set address if mpcd e.g. gets killed and restarted.
+ * If we do not do it now we have to wait for the next LE_ARP
+ */
+ if ( memcmp(mpc->mps_ctrl_addr, empty, ATM_ESA_LEN) != 0 )
+ send_set_mps_ctrl_addr(mpc->mps_ctrl_addr, mpc);
+ }
+
+ MOD_INC_USE_COUNT;
+ return arg;
}
static void send_set_mps_ctrl_addr(char *addr, struct mpoa_client *mpc)
{
- struct k_message mesg;
+ struct k_message mesg;
- memcpy (mpc->mps_ctrl_addr, addr, ATM_ESA_LEN);
-
- mesg.type = SET_MPS_CTRL_ADDR;
- memcpy(mesg.MPS_ctrl, addr, ATM_ESA_LEN);
- msg_to_mpoad(&mesg, mpc);
+ memcpy (mpc->mps_ctrl_addr, addr, ATM_ESA_LEN);
+
+ mesg.type = SET_MPS_CTRL_ADDR;
+ memcpy(mesg.MPS_ctrl, addr, ATM_ESA_LEN);
+ msg_to_mpoad(&mesg, mpc);
- return;
+ return;
}
static void mpoad_close(struct atm_vcc *vcc)
{
- unsigned long flags;
- struct mpoa_client *mpc;
- struct sk_buff *skb;
-
- mpc = find_mpc_by_vcc(vcc);
- if (mpc == NULL) {
- printk("mpoa: mpoad_close: did not find MPC\n");
- return;
- }
- if (!mpc->mpoad_vcc) {
- printk("mpoa: mpoad_close: close for non-present mpoad\n");
- return;
- }
-
- mpc->mpoad_vcc = NULL;
- if (mpc->dev) {
- struct lec_priv *priv = (struct lec_priv *)mpc->dev->priv;
- priv->lane2_ops->associate_indicator = NULL;
- stop_mpc(mpc);
- }
-
- /* clear the caches */
- write_lock_irqsave(&mpc->ingress_lock, flags);
- while(mpc->in_ops->cache_remove(mpc->in_cache, mpc));
- write_unlock_irqrestore(&mpc->ingress_lock, flags);
-
- write_lock_irqsave(&mpc->egress_lock, flags);
- while(mpc->eg_ops->cache_remove(mpc->eg_cache, mpc));
- write_unlock_irqrestore(&mpc->egress_lock, flags);
+ struct mpoa_client *mpc;
+ struct sk_buff *skb;
+
+ mpc = find_mpc_by_vcc(vcc);
+ if (mpc == NULL) {
+ printk("mpoa: mpoad_close: did not find MPC\n");
+ return;
+ }
+ if (!mpc->mpoad_vcc) {
+ printk("mpoa: mpoad_close: close for non-present mpoad\n");
+ return;
+ }
+
+ mpc->mpoad_vcc = NULL;
+ if (mpc->dev) {
+ struct lec_priv *priv = (struct lec_priv *)mpc->dev->priv;
+ priv->lane2_ops->associate_indicator = NULL;
+ stop_mpc(mpc);
+ }
+
+ mpc->in_ops->destroy_cache(mpc);
+ mpc->eg_ops->destroy_cache(mpc);
while ( (skb = skb_dequeue(&vcc->recvq)) ){
- atm_return(vcc, skb->truesize);
- kfree_skb(skb);
- }
-
- printk("mpoa: (%s) going down\n",
- (mpc->dev) ? mpc->dev->name : "<unknown>");
- MOD_DEC_USE_COUNT;
-
- return;
+ atm_return(vcc, skb->truesize);
+ kfree_skb(skb);
+ }
+
+ printk("mpoa: (%s) going down\n",
+ (mpc->dev) ? mpc->dev->name : "<unknown>");
+ MOD_DEC_USE_COUNT;
+
+ return;
}
/*
@@ -862,163 +864,163 @@ static void mpoad_close(struct atm_vcc *vcc)
*/
static int msg_from_mpoad(struct atm_vcc *vcc, struct sk_buff *skb)
{
-
- struct mpoa_client *mpc = find_mpc_by_vcc(vcc);
- struct k_message *mesg = (struct k_message*)skb->data;
- atomic_sub(skb->truesize+ATM_PDU_OVHD, &vcc->tx_inuse);
-
- if (mpc == NULL) {
- printk("mpoa: msg_from_mpoad: no mpc found\n");
- return 0;
- }
- dprintk("mpoa: (%s) msg_from_mpoad:", (mpc->dev) ? mpc->dev->name : "<unknown>");
- switch(mesg->type) {
- case MPOA_RES_REPLY_RCVD:
- dprintk(" mpoa_res_reply_rcvd\n");
- MPOA_res_reply_rcvd(mesg, mpc);
- break;
- case MPOA_TRIGGER_RCVD:
- dprintk(" mpoa_trigger_rcvd\n");
- MPOA_trigger_rcvd(mesg, mpc);
- break;
- case INGRESS_PURGE_RCVD:
- dprintk(" nhrp_purge_rcvd\n");
- ingress_purge_rcvd(mesg, mpc);
- break;
- case EGRESS_PURGE_RCVD:
- dprintk(" egress_purge_reply_rcvd\n");
- egress_purge_rcvd(mesg, mpc);
- break;
- case MPS_DEATH:
- dprintk(" mps_death\n");
- mps_death(mesg, mpc);
- break;
- case CACHE_IMPOS_RCVD:
- dprintk(" cache_impos_rcvd\n");
- MPOA_cache_impos_rcvd(mesg, mpc);
- break;
- case SET_MPC_CTRL_ADDR:
- dprintk(" set_mpc_ctrl_addr\n");
- set_mpc_ctrl_addr_rcvd(mesg, mpc);
- break;
+
+ struct mpoa_client *mpc = find_mpc_by_vcc(vcc);
+ struct k_message *mesg = (struct k_message*)skb->data;
+ atomic_sub(skb->truesize+ATM_PDU_OVHD, &vcc->tx_inuse);
+
+ if (mpc == NULL) {
+ printk("mpoa: msg_from_mpoad: no mpc found\n");
+ return 0;
+ }
+ dprintk("mpoa: (%s) msg_from_mpoad:", (mpc->dev) ? mpc->dev->name : "<unknown>");
+ switch(mesg->type) {
+ case MPOA_RES_REPLY_RCVD:
+ dprintk(" mpoa_res_reply_rcvd\n");
+ MPOA_res_reply_rcvd(mesg, mpc);
+ break;
+ case MPOA_TRIGGER_RCVD:
+ dprintk(" mpoa_trigger_rcvd\n");
+ MPOA_trigger_rcvd(mesg, mpc);
+ break;
+ case INGRESS_PURGE_RCVD:
+ dprintk(" nhrp_purge_rcvd\n");
+ ingress_purge_rcvd(mesg, mpc);
+ break;
+ case EGRESS_PURGE_RCVD:
+ dprintk(" egress_purge_reply_rcvd\n");
+ egress_purge_rcvd(mesg, mpc);
+ break;
+ case MPS_DEATH:
+ dprintk(" mps_death\n");
+ mps_death(mesg, mpc);
+ break;
+ case CACHE_IMPOS_RCVD:
+ dprintk(" cache_impos_rcvd\n");
+ MPOA_cache_impos_rcvd(mesg, mpc);
+ break;
+ case SET_MPC_CTRL_ADDR:
+ dprintk(" set_mpc_ctrl_addr\n");
+ set_mpc_ctrl_addr_rcvd(mesg, mpc);
+ break;
case SET_MPS_MAC_ADDR:
- dprintk(" set_mps_mac_addr\n");
+ dprintk(" set_mps_mac_addr\n");
set_mps_mac_addr_rcvd(mesg, mpc);
break;
case CLEAN_UP_AND_EXIT:
- dprintk(" clean_up_and_exit\n");
- clean_up(mesg, mpc, DIE);
- break;
- case RELOAD:
- dprintk(" reload\n");
- clean_up(mesg, mpc, RELOAD);
- break;
- case SET_MPC_PARAMS:
- dprintk(" set_mpc_params\n");
- mpc->parameters = mesg->content.params;
- break;
- default:
- dprintk(" unknown message %d\n", mesg->type);
- break;
- }
- kfree_skb(skb);
-
- return 0;
+ dprintk(" clean_up_and_exit\n");
+ clean_up(mesg, mpc, DIE);
+ break;
+ case RELOAD:
+ dprintk(" reload\n");
+ clean_up(mesg, mpc, RELOAD);
+ break;
+ case SET_MPC_PARAMS:
+ dprintk(" set_mpc_params\n");
+ mpc->parameters = mesg->content.params;
+ break;
+ default:
+ dprintk(" unknown message %d\n", mesg->type);
+ break;
+ }
+ kfree_skb(skb);
+
+ return 0;
}
+/* Remember that this function may not do things that sleep */
int msg_to_mpoad(struct k_message *mesg, struct mpoa_client *mpc)
{
- struct sk_buff *skb;
-
- if (mpc == NULL || !mpc->mpoad_vcc) {
- printk("mpoa: msg_to_mpoad: mesg %d to a non-existent mpoad\n", mesg->type);
- return -ENXIO;
- }
-
- skb = alloc_skb(sizeof(struct k_message), GFP_ATOMIC);
- if (skb == NULL)
- return -ENOMEM;
- 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->recvq, skb);
- wake_up(&mpc->mpoad_vcc->sleep);
-
- return 0;
+ struct sk_buff *skb;
+
+ if (mpc == NULL || !mpc->mpoad_vcc) {
+ printk("mpoa: msg_to_mpoad: mesg %d to a non-existent mpoad\n", mesg->type);
+ return -ENXIO;
+ }
+
+ skb = alloc_skb(sizeof(struct k_message), GFP_ATOMIC);
+ if (skb == NULL)
+ return -ENOMEM;
+ 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->recvq, skb);
+ wake_up(&mpc->mpoad_vcc->sleep);
+
+ return 0;
}
static int mpoa_event_listener(struct notifier_block *mpoa_notifier, unsigned long event, void *dev_ptr)
{
- struct net_device *dev;
- struct mpoa_client *mpc;
- struct lec_priv *priv;
-
- dev = (struct net_device *)dev_ptr;
- if (dev->name == NULL || strncmp(dev->name, "lec", 3))
- return NOTIFY_DONE; /* we are only interested in lec:s */
-
- switch (event) {
- case NETDEV_REGISTER: /* a new lec device was allocated */
- priv = (struct lec_priv *)dev->priv;
- if (priv->lane_version < 2)
- break;
- priv->lane2_ops->associate_indicator = lane2_assoc_ind;
- mpc = find_mpc_by_itfnum(priv->itfnum);
- if (mpc == NULL) {
- dprintk("mpoa: mpoa_event_listener: allocating new mpc for %s\n",
- dev->name);
- mpc = alloc_mpc();
- if (mpc == NULL) {
- printk("mpoa: mpoa_event_listener: no new mpc");
- break;
- }
- }
- mpc->dev_num = priv->itfnum;
- mpc->dev = dev;
- dprintk("mpoa: (%s) was initialized\n", dev->name);
- break;
- case NETDEV_UNREGISTER:
- /* the lec device was deallocated */
- mpc = find_mpc_by_lec(dev);
- if (mpc == NULL)
- break;
- dprintk("mpoa: device (%s) was deallocated\n", dev->name);
- stop_mpc(mpc);
- mpc->dev = NULL;
- break;
- case NETDEV_UP:
- /* the dev was ifconfig'ed up */
- mpc = find_mpc_by_lec(dev);
- if (mpc == NULL)
- break;
- if (mpc->mpoad_vcc != NULL) {
- start_mpc(mpc, dev);
- }
- break;
- case NETDEV_DOWN:
- /* the dev was ifconfig'ed down */
- /* this means dev->start == 0 and
- * the flow of packets from the
- * upper layer stops
- */
- mpc = find_mpc_by_lec(dev);
- if (mpc == NULL)
- break;
- if (mpc->mpoad_vcc != NULL) {
- stop_mpc(mpc);
- }
- break;
- case NETDEV_REBOOT:
- case NETDEV_CHANGE:
- case NETDEV_CHANGEMTU:
- case NETDEV_CHANGEADDR:
- case NETDEV_GOING_DOWN:
- break;
- default:
- break;
- }
-
- return NOTIFY_DONE;
+ struct net_device *dev;
+ struct mpoa_client *mpc;
+ struct lec_priv *priv;
+
+ dev = (struct net_device *)dev_ptr;
+ if (dev->name == NULL || strncmp(dev->name, "lec", 3))
+ return NOTIFY_DONE; /* we are only interested in lec:s */
+
+ switch (event) {
+ case NETDEV_REGISTER: /* a new lec device was allocated */
+ priv = (struct lec_priv *)dev->priv;
+ if (priv->lane_version < 2)
+ break;
+ priv->lane2_ops->associate_indicator = lane2_assoc_ind;
+ mpc = find_mpc_by_itfnum(priv->itfnum);
+ if (mpc == NULL) {
+ dprintk("mpoa: mpoa_event_listener: allocating new mpc for %s\n",
+ dev->name);
+ mpc = alloc_mpc();
+ if (mpc == NULL) {
+ printk("mpoa: mpoa_event_listener: no new mpc");
+ break;
+ }
+ }
+ mpc->dev_num = priv->itfnum;
+ mpc->dev = dev;
+ dprintk("mpoa: (%s) was initialized\n", dev->name);
+ break;
+ case NETDEV_UNREGISTER:
+ /* the lec device was deallocated */
+ mpc = find_mpc_by_lec(dev);
+ if (mpc == NULL)
+ break;
+ dprintk("mpoa: device (%s) was deallocated\n", dev->name);
+ stop_mpc(mpc);
+ mpc->dev = NULL;
+ break;
+ case NETDEV_UP:
+ /* the dev was ifconfig'ed up */
+ mpc = find_mpc_by_lec(dev);
+ if (mpc == NULL)
+ break;
+ if (mpc->mpoad_vcc != NULL) {
+ start_mpc(mpc, dev);
+ }
+ break;
+ case NETDEV_DOWN:
+ /* the dev was ifconfig'ed down */
+ /* this means that the flow of packets from the
+ * upper layer stops
+ */
+ mpc = find_mpc_by_lec(dev);
+ if (mpc == NULL)
+ break;
+ if (mpc->mpoad_vcc != NULL) {
+ stop_mpc(mpc);
+ }
+ break;
+ case NETDEV_REBOOT:
+ case NETDEV_CHANGE:
+ case NETDEV_CHANGEMTU:
+ case NETDEV_CHANGEADDR:
+ case NETDEV_GOING_DOWN:
+ break;
+ default:
+ break;
+ }
+
+ return NOTIFY_DONE;
}
/*
@@ -1027,33 +1029,36 @@ static int mpoa_event_listener(struct notifier_block *mpoa_notifier, unsigned lo
*/
-static void MPOA_trigger_rcvd(struct k_message *msg, struct mpoa_client *client)
+static void MPOA_trigger_rcvd(struct k_message *msg, struct mpoa_client *mpc)
{
- uint32_t dst_ip = msg->content.in_info.in_dst_ip;
- in_cache_entry *entry;
+ uint32_t dst_ip = msg->content.in_info.in_dst_ip;
+ in_cache_entry *entry;
- entry = client->in_ops->search(dst_ip, client);
- if( entry == NULL ){
- entry = client->in_ops->new_entry(dst_ip, client);
- entry->entry_state = INGRESS_RESOLVING;
+ entry = mpc->in_ops->get(dst_ip, mpc);
+ if(entry == NULL){
+ entry = mpc->in_ops->add_entry(dst_ip, mpc);
+ entry->entry_state = INGRESS_RESOLVING;
msg->type = SND_MPOA_RES_RQST;
- msg->content.in_info = entry->ctrl_info;
- msg_to_mpoad(msg,client);
+ msg->content.in_info = entry->ctrl_info;
+ msg_to_mpoad(msg, mpc);
do_gettimeofday(&(entry->reply_wait));
+ mpc->in_ops->put(entry);
return;
- }
-
- if( entry->entry_state == INGRESS_INVALID ){
- entry->entry_state = INGRESS_RESOLVING;
+ }
+
+ if(entry->entry_state == INGRESS_INVALID){
+ entry->entry_state = INGRESS_RESOLVING;
msg->type = SND_MPOA_RES_RQST;
- msg->content.in_info = entry->ctrl_info;
- msg_to_mpoad(msg,client);
+ msg->content.in_info = entry->ctrl_info;
+ msg_to_mpoad(msg, mpc);
do_gettimeofday(&(entry->reply_wait));
- return;
- }
-
- printk("mpoa: (%s) MPOA_trigger_rcvd: entry already in resolving state\n",
- (client->dev) ? client->dev->name : "<unknown>");
+ mpc->in_ops->put(entry);
+ return;
+ }
+
+ printk("mpoa: (%s) MPOA_trigger_rcvd: entry already in resolving state\n",
+ (mpc->dev) ? mpc->dev->name : "<unknown>");
+ mpc->in_ops->put(entry);
return;
}
@@ -1061,30 +1066,36 @@ static void MPOA_trigger_rcvd(struct k_message *msg, struct mpoa_client *client)
* Things get complicated because we have to check if there's an egress
* shortcut with suitable traffic parameters we could use.
*/
-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;
+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;
struct atm_mpoa_qos *qos = atm_mpoa_search_qos(dst_ip);
- eg_cache_entry *eg_entry = client->eg_ops->search_by_src_ip(dst_ip, client);
+ eg_cache_entry *eg_entry = client->eg_ops->get_by_src_ip(dst_ip, client);
+
if(eg_entry && eg_entry->shortcut){
- if(eg_entry->shortcut->qos.txtp.traffic_class &
+ if(eg_entry->shortcut->qos.txtp.traffic_class &
msg->qos.txtp.traffic_class &
(qos ? qos->qos.txtp.traffic_class : ATM_UBR | ATM_CBR)){
- if(eg_entry->shortcut->qos.txtp.traffic_class == ATM_UBR)
- entry->shortcut = eg_entry->shortcut;
+ if(eg_entry->shortcut->qos.txtp.traffic_class == ATM_UBR)
+ entry->shortcut = eg_entry->shortcut;
else if(eg_entry->shortcut->qos.txtp.max_pcr > 0)
- entry->shortcut = eg_entry->shortcut;
+ entry->shortcut = eg_entry->shortcut;
}
if(entry->shortcut){
- dprintk("mpoa: (%s) using egress SVC to reach %d.%d.%d.%d\n",client->dev->name, ip[0], ip[1], ip[2], ip[3]);
+ dprintk("mpoa: (%s) using egress SVC to reach %u.%u.%u.%u\n",client->dev->name, NIPQUAD(ip));
+ client->eg_ops->put(eg_entry);
return;
}
}
+ if (eg_entry != NULL)
+ client->eg_ops->put(eg_entry);
+
/* No luck in the egress cache we must open an ingress SVC */
msg->type = OPEN_INGRESS_SVC;
if (qos && (qos->qos.txtp.traffic_class == msg->qos.txtp.traffic_class))
{
- msg->qos = qos->qos;
+ msg->qos = qos->qos;
printk("mpoa: (%s) trying to get a CBR shortcut\n",client->dev->name);
}
else memset(&msg->qos,0,sizeof(struct atm_qos));
@@ -1092,45 +1103,49 @@ static void check_qos_and_open_shortcut(struct k_message *msg, struct mpoa_clien
return;
}
-static void MPOA_res_reply_rcvd(struct k_message *msg, struct mpoa_client *client)
+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;
- in_cache_entry *entry = client->in_ops->search(dst_ip, client);
+ uint32_t 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 %d.%d.%d.%d\n", client->dev->name, ip[0], ip[1], ip[2], ip[3]);
- ddprintk("mpoa: (%s) MPOA_res_reply_rcvd() entry = %p", client->dev->name, entry);
- if(entry == NULL){
- printk("\nmpoa: (%s) ARGH, received res. reply for an entry that doesn't exist.\n", client->dev->name);
- return;
- }
- ddprintk(" entry_state = %d ", entry->entry_state);
-
- if (entry->entry_state == INGRESS_RESOLVED) {
- printk("\nmpoa: (%s) MPOA_res_reply_rcvd for RESOLVED entry!\n", client->dev->name);
- return;
- }
-
- entry->ctrl_info = msg->content.in_info;
- do_gettimeofday(&(entry->tv));
- do_gettimeofday(&(entry->reply_wait)); /* Used in refreshing func from now on */
- entry->refresh_time = 0;
- ddprintk("entry->shortcut = %p\n", entry->shortcut);
+ dprintk("mpoa: (%s) MPOA_res_reply_rcvd: ip %u.%u.%u.%u\n", mpc->dev->name, NIPQUAD(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);
+ return;
+ }
+ ddprintk(" entry_state = %d ", entry->entry_state);
+
+ if (entry->entry_state == INGRESS_RESOLVED) {
+ printk("\nmpoa: (%s) MPOA_res_reply_rcvd for RESOLVED entry!\n", mpc->dev->name);
+ mpc->in_ops->put(entry);
+ return;
+ }
+
+ entry->ctrl_info = msg->content.in_info;
+ do_gettimeofday(&(entry->tv));
+ do_gettimeofday(&(entry->reply_wait)); /* Used in refreshing func from now on */
+ entry->refresh_time = 0;
+ ddprintk("entry->shortcut = %p\n", entry->shortcut);
if(entry->entry_state == INGRESS_RESOLVING && entry->shortcut != NULL){
- entry->entry_state = INGRESS_RESOLVED;
+ entry->entry_state = INGRESS_RESOLVED;
+ mpc->in_ops->put(entry);
return; /* Shortcut already open... */
}
if (entry->shortcut != NULL) {
printk("mpoa: (%s) MPOA_res_reply_rcvd: entry->shortcut != NULL, impossible!\n",
- client->dev->name);
+ mpc->dev->name);
+ mpc->in_ops->put(entry);
return;
}
- check_qos_and_open_shortcut(msg, client, entry);
+ check_qos_and_open_shortcut(msg, mpc, entry);
entry->entry_state = INGRESS_RESOLVED;
+ mpc->in_ops->put(entry);
return;
@@ -1138,73 +1153,79 @@ static void MPOA_res_reply_rcvd(struct k_message *msg, struct mpoa_client *clien
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;
+ uint32_t dst_ip = msg->content.in_info.in_dst_ip;
+ uint32_t mask = msg->ip_mask;
unsigned char *ip = (unsigned char *)&dst_ip;
+ in_cache_entry *entry = mpc->in_ops->get_with_mask(dst_ip, mpc, mask);
- in_cache_entry *entry = mpc->in_ops->search_with_mask(dst_ip, mpc, mask);
- if( entry == NULL ){
- printk("mpoa: (%s) ingress_purge_rcvd: recieved a purge for an entry that doesn't exist, ", mpc->dev->name);
- printk("ip = %u.%u.%u.%u\n", ip[0], ip[1], ip[2], ip[3]);
- return;
- }
- while(entry != NULL){
- 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->in_ops->cache_remove(entry, mpc);
- entry = mpc->in_ops->search_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]);
+ return;
}
- 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]);
+ write_lock_bh(&mpc->ingress_lock);
+ mpc->in_ops->remove_entry(entry, mpc);
+ write_unlock_bh(&mpc->ingress_lock);
+ mpc->in_ops->put(entry);
+ entry = mpc->in_ops->get_with_mask(dst_ip, mpc, mask);
+ } while (entry != NULL);
+
+ return;
}
static void egress_purge_rcvd(struct k_message *msg, struct mpoa_client *mpc)
{
- unsigned long flags;
- uint32_t cache_id = msg->content.eg_info.cache_id;
- eg_cache_entry *entry = mpc->eg_ops->search_by_cache_id(cache_id, mpc);
-
- if( entry == NULL ){
- printk("mpoa: (%s) egress_purge_rcvd: received a purge reply for an entry that doesn't exist\n", mpc->dev->name);
- return;
- }
-
- write_lock_irqsave(&mpc->egress_lock, flags);
- mpc->eg_ops->cache_remove(entry, mpc);
- write_unlock_irqrestore(&mpc->egress_lock, flags);
-
- return;
+ uint32_t 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) {
+ dprintk("mpoa: (%s) egress_purge_rcvd: purge for a non-existing entry\n", mpc->dev->name);
+ return;
+ }
+
+ write_lock_irq(&mpc->egress_lock);
+ mpc->eg_ops->remove_entry(entry, mpc);
+ write_unlock_irq(&mpc->egress_lock);
+
+ mpc->eg_ops->put(entry);
+
+ return;
}
static void purge_egress_shortcut(struct atm_vcc *vcc, eg_cache_entry *entry)
{
- struct k_message *purge_msg;
- struct sk_buff *skb;
-
- dprintk("mpoa: purge_egress_shortcut: entering\n");
- if (vcc == NULL) {
- printk("mpoa: purge_egress_shortcut: vcc == NULL\n");
- return;
- }
-
- skb = alloc_skb(sizeof(struct k_message), GFP_ATOMIC);
- if (skb == NULL) {
- printk("mpoa: purge_egress_shortcut: out of memory\n");
- return;
- }
-
- skb_put(skb, sizeof(struct k_message));
- memset(skb->data, 0, sizeof(struct k_message));
- purge_msg = (struct k_message *)skb->data;
- purge_msg->type = DATA_PLANE_PURGE;
- if (entry != NULL)
- purge_msg->content.eg_info = entry->ctrl_info;
-
- atm_force_charge(vcc, skb->truesize);
- skb_queue_tail(&vcc->recvq, skb);
- wake_up(&vcc->sleep);
- dprintk("mpoa: purge_egress_shortcut: exiting:\n");
-
- return;
+ struct k_message *purge_msg;
+ struct sk_buff *skb;
+
+ dprintk("mpoa: purge_egress_shortcut: entering\n");
+ if (vcc == NULL) {
+ printk("mpoa: purge_egress_shortcut: vcc == NULL\n");
+ return;
+ }
+
+ skb = alloc_skb(sizeof(struct k_message), GFP_ATOMIC);
+ if (skb == NULL) {
+ printk("mpoa: purge_egress_shortcut: out of memory\n");
+ return;
+ }
+
+ skb_put(skb, sizeof(struct k_message));
+ memset(skb->data, 0, sizeof(struct k_message));
+ purge_msg = (struct k_message *)skb->data;
+ purge_msg->type = DATA_PLANE_PURGE;
+ if (entry != NULL)
+ purge_msg->content.eg_info = entry->ctrl_info;
+
+ atm_force_charge(vcc, skb->truesize);
+ skb_queue_tail(&vcc->recvq, skb);
+ wake_up(&vcc->sleep);
+ dprintk("mpoa: purge_egress_shortcut: exiting:\n");
+
+ return;
}
/*
@@ -1213,104 +1234,102 @@ static void purge_egress_shortcut(struct atm_vcc *vcc, eg_cache_entry *entry)
*/
static void mps_death( struct k_message * msg, struct mpoa_client * mpc )
{
+ eg_cache_entry *entry;
- unsigned long flags;
- eg_cache_entry *entry;
-
- dprintk("mpoa: (%s) mps_death:\n", mpc->dev->name);
+ dprintk("mpoa: (%s) mps_death:\n", mpc->dev->name);
- if(memcmp(msg->MPS_ctrl, mpc->mps_ctrl_addr, ATM_ESA_LEN)){
- printk("mpoa: (%s) mps_death: wrong MPS\n", mpc->dev->name);
- return;
- }
-
- entry = mpc->eg_cache;
- while (entry != NULL) {
- purge_egress_shortcut(entry->shortcut, entry);
- entry = entry->next;
- }
+ if(memcmp(msg->MPS_ctrl, mpc->mps_ctrl_addr, ATM_ESA_LEN)){
+ printk("mpoa: (%s) mps_death: wrong MPS\n", mpc->dev->name);
+ return;
+ }
- write_lock_irqsave(&mpc->ingress_lock, flags);
- while(mpc->in_ops->cache_remove(mpc->in_cache, mpc));
- write_unlock_irqrestore(&mpc->ingress_lock, flags);
+ /* FIXME: This knows too much of the cache structure */
+ read_lock_irq(&mpc->egress_lock);
+ entry = mpc->eg_cache;
+ while (entry != NULL) {
+ purge_egress_shortcut(entry->shortcut, entry);
+ entry = entry->next;
+ }
+ read_unlock_irq(&mpc->egress_lock);
- write_lock_irqsave(&mpc->egress_lock, flags);
- while(mpc->eg_ops->cache_remove(mpc->eg_cache, mpc));
- write_unlock_irqrestore(&mpc->egress_lock, flags);
+ mpc->in_ops->destroy_cache(mpc);
+ mpc->eg_ops->destroy_cache(mpc);
- return;
+ return;
}
-static void MPOA_cache_impos_rcvd( struct k_message * msg, struct mpoa_client * mpc){
-
- uint16_t holding_time;
- unsigned long flags;
- eg_cache_entry *entry = mpc->eg_ops->search_by_cache_id(msg->content.eg_info.cache_id, mpc);
-
- holding_time = msg->content.eg_info.holding_time;
- dprintk("mpoa: (%s) MPOA_cache_impos_rcvd: entry = %p, holding_time = %u\n",
- mpc->dev->name, entry, holding_time);
- if(entry == NULL && holding_time) {
- mpc->eg_ops->new_entry(msg, mpc);
- return;
- }
- if(holding_time){
- mpc->eg_ops->update(entry, holding_time);
- return;
- }
-
- write_lock_irqsave(&mpc->egress_lock, flags);
- mpc->eg_ops->cache_remove(entry, mpc);
- write_unlock_irqrestore(&mpc->egress_lock, flags);
-
-
- return;
+static void MPOA_cache_impos_rcvd( struct k_message * msg, struct mpoa_client * mpc)
+{
+ uint16_t holding_time;
+ eg_cache_entry *entry = mpc->eg_ops->get_by_cache_id(msg->content.eg_info.cache_id, mpc);
+
+ holding_time = msg->content.eg_info.holding_time;
+ dprintk("mpoa: (%s) MPOA_cache_impos_rcvd: entry = %p, holding_time = %u\n",
+ mpc->dev->name, entry, holding_time);
+ if(entry == NULL && holding_time) {
+ entry = mpc->eg_ops->add_entry(msg, mpc);
+ mpc->eg_ops->put(entry);
+ return;
+ }
+ if(holding_time){
+ mpc->eg_ops->update(entry, holding_time);
+ return;
+ }
+
+ write_lock_irq(&mpc->egress_lock);
+ mpc->eg_ops->remove_entry(entry, mpc);
+ write_unlock_irq(&mpc->egress_lock);
+
+ mpc->eg_ops->put(entry);
+
+ return;
}
static void set_mpc_ctrl_addr_rcvd(struct k_message *mesg, struct mpoa_client *mpc)
{
- struct lec_priv *priv;
- int i, retval ;
-
- uint8_t tlv[4 + 1 + 1 + 1 + ATM_ESA_LEN];
-
- tlv[0] = 00; tlv[1] = 0xa0; tlv[2] = 0x3e; tlv[3] = 0x2a; /* type */
- tlv[4] = 1 + 1 + ATM_ESA_LEN; /* length */
- tlv[5] = 0x02; /* MPOA client */
- tlv[6] = 0x00; /* number of MPS MAC addresses */
-
- memcpy(&tlv[7], mesg->MPS_ctrl, ATM_ESA_LEN); /* MPC ctrl ATM addr */
- memcpy(mpc->our_ctrl_addr, mesg->MPS_ctrl, ATM_ESA_LEN);
-
- dprintk("mpoa: (%s) setting MPC ctrl ATM address to ",
- (mpc->dev) ? mpc->dev->name : "<unknown>");
- for (i = 7; i < sizeof(tlv); i++)
- dprintk("%02x ", tlv[i]);
- dprintk("\n");
-
- if (mpc->dev) {
- priv = (struct lec_priv *)mpc->dev->priv;
- retval = priv->lane2_ops->associate_req(mpc->dev, mpc->dev->dev_addr, tlv, sizeof(tlv));
- if (retval == 0)
- printk("mpoa: (%s) MPOA device type TLV association failed\n", mpc->dev->name);
- retval = priv->lane2_ops->resolve(mpc->dev, NULL, 1, NULL, NULL);
- if (retval < 0)
- printk("mpoa: (%s) targetless LE_ARP request failed\n", mpc->dev->name);
- }
-
- return;
+ struct lec_priv *priv;
+ int i, retval ;
+
+ uint8_t tlv[4 + 1 + 1 + 1 + ATM_ESA_LEN];
+
+ tlv[0] = 00; tlv[1] = 0xa0; tlv[2] = 0x3e; tlv[3] = 0x2a; /* type */
+ tlv[4] = 1 + 1 + ATM_ESA_LEN; /* length */
+ tlv[5] = 0x02; /* MPOA client */
+ tlv[6] = 0x00; /* number of MPS MAC addresses */
+
+ memcpy(&tlv[7], mesg->MPS_ctrl, ATM_ESA_LEN); /* MPC ctrl ATM addr */
+ memcpy(mpc->our_ctrl_addr, mesg->MPS_ctrl, ATM_ESA_LEN);
+
+ dprintk("mpoa: (%s) setting MPC ctrl ATM address to ",
+ (mpc->dev) ? mpc->dev->name : "<unknown>");
+ for (i = 7; i < sizeof(tlv); i++)
+ dprintk("%02x ", tlv[i]);
+ dprintk("\n");
+
+ if (mpc->dev) {
+ priv = (struct lec_priv *)mpc->dev->priv;
+ retval = priv->lane2_ops->associate_req(mpc->dev, mpc->dev->dev_addr, tlv, sizeof(tlv));
+ if (retval == 0)
+ printk("mpoa: (%s) MPOA device type TLV association failed\n", mpc->dev->name);
+ retval = priv->lane2_ops->resolve(mpc->dev, NULL, 1, NULL, NULL);
+ if (retval < 0)
+ printk("mpoa: (%s) targetless LE_ARP request failed\n", mpc->dev->name);
+ }
+
+ return;
}
-static void set_mps_mac_addr_rcvd(struct k_message *msg, struct mpoa_client *client){
+static void set_mps_mac_addr_rcvd(struct k_message *msg, struct mpoa_client *client)
+{
- if(client->number_of_mps_macs)
- kfree(client->mps_macs);
- client->number_of_mps_macs = 0;
+ if(client->number_of_mps_macs)
+ kfree(client->mps_macs);
+ client->number_of_mps_macs = 0;
client->mps_macs = kmalloc(ETH_ALEN,GFP_KERNEL);
- if (client->mps_macs == NULL) {
- printk("mpoa: set_mps_mac_addr_rcvd: out of memory\n");
- return;
- }
+ 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);
@@ -1320,22 +1339,23 @@ static void set_mps_mac_addr_rcvd(struct k_message *msg, struct mpoa_client *cli
/*
* purge egress cache and tell daemon to 'action' (DIE, RELOAD)
*/
-static void clean_up(struct k_message *msg, struct mpoa_client *mpc, int action){
+static void clean_up(struct k_message *msg, struct mpoa_client *mpc, int action)
+{
- unsigned long flags;
- eg_cache_entry *entry;
+ eg_cache_entry *entry;
msg->type = SND_EGRESS_PURGE;
- read_lock_irqsave(&mpc->egress_lock, flags);
- entry = mpc->eg_cache;
- while(entry != NULL){
- msg->content.eg_info = entry->ctrl_info;
- dprintk("mpoa: cache_id %u\n", entry->ctrl_info.cache_id);
+ /* FIXME: This knows too much of the cache structure */
+ read_lock_irq(&mpc->egress_lock);
+ entry = mpc->eg_cache;
+ while (entry != NULL){
+ msg->content.eg_info = entry->ctrl_info;
+ dprintk("mpoa: cache_id %u\n", entry->ctrl_info.cache_id);
msg_to_mpoad(msg, mpc);
entry = entry->next;
}
- read_unlock_irqrestore(&mpc->egress_lock, flags);
+ read_unlock_irq(&mpc->egress_lock);
msg->type = action;
msg_to_mpoad(msg, mpc);
@@ -1344,116 +1364,116 @@ static void clean_up(struct k_message *msg, struct mpoa_client *mpc, int action)
static void mpc_timer_refresh()
{
- mpc_timer.expires = jiffies + (MPC_P2 * HZ);
- mpc_timer.data = mpc_timer.expires;
- mpc_timer.function = mpc_cache_check;
- add_timer(&mpc_timer);
-
- return;
+ mpc_timer.expires = jiffies + (MPC_P2 * HZ);
+ mpc_timer.data = mpc_timer.expires;
+ mpc_timer.function = mpc_cache_check;
+ add_timer(&mpc_timer);
+
+ return;
}
static void mpc_cache_check( unsigned long checking_time )
{
- struct mpoa_client *mpc = mpcs;
- static unsigned long previous_resolving_check_time = 0;
- static unsigned long previous_refresh_time = 0;
-
- while( mpc != NULL ){
- mpc->in_ops->clear_count(mpc);
+ struct mpoa_client *mpc = mpcs;
+ static unsigned long previous_resolving_check_time = 0;
+ static unsigned long previous_refresh_time = 0;
+
+ while( mpc != NULL ){
+ mpc->in_ops->clear_count(mpc);
mpc->eg_ops->clear_expired(mpc);
- if(checking_time - previous_resolving_check_time > mpc->parameters.mpc_p4 * HZ ){
- mpc->in_ops->check_resolving(mpc);
- previous_resolving_check_time = checking_time;
- }
- if(checking_time - previous_refresh_time > mpc->parameters.mpc_p5 * HZ ){
- mpc->in_ops->refresh(mpc);
- previous_refresh_time = checking_time;
- }
- mpc = mpc->next;
- }
- mpc_timer_refresh();
-
- return;
+ if(checking_time - previous_resolving_check_time > mpc->parameters.mpc_p4 * HZ ){
+ mpc->in_ops->check_resolving(mpc);
+ previous_resolving_check_time = checking_time;
+ }
+ if(checking_time - previous_refresh_time > mpc->parameters.mpc_p5 * HZ ){
+ mpc->in_ops->refresh(mpc);
+ previous_refresh_time = checking_time;
+ }
+ mpc = mpc->next;
+ }
+ mpc_timer_refresh();
+
+ return;
}
void atm_mpoa_init_ops(struct atm_mpoa_ops *ops)
{
- ops->mpoad_attach = atm_mpoa_mpoad_attach;
- ops->vcc_attach = atm_mpoa_vcc_attach;
+ ops->mpoad_attach = atm_mpoa_mpoad_attach;
+ ops->vcc_attach = atm_mpoa_vcc_attach;
#ifdef CONFIG_PROC_FS
if(mpc_proc_init() != 0)
- printk(KERN_INFO "mpoa: failed to initialize /proc/mpoa\n");
+ printk(KERN_INFO "mpoa: failed to initialize /proc/mpoa\n");
else
- printk(KERN_INFO "mpoa: /proc/mpoa initialized\n");
+ printk(KERN_INFO "mpoa: /proc/mpoa initialized\n");
#endif
- printk("mpc.c: " __DATE__ " " __TIME__ " initialized\n");
+ printk("mpc.c: " __DATE__ " " __TIME__ " initialized\n");
- return;
+ return;
}
#ifdef MODULE
int init_module(void)
{
- extern struct atm_mpoa_ops atm_mpoa_ops;
+ extern struct atm_mpoa_ops atm_mpoa_ops;
atm_mpoa_init_ops(&atm_mpoa_ops);
- return 0;
+ return 0;
}
void cleanup_module(void)
{
- extern struct atm_mpoa_ops atm_mpoa_ops;
- struct mpoa_client *mpc, *tmp;
- struct atm_mpoa_qos *qos, *nextqos;
- struct lec_priv *priv;
-
- if (MOD_IN_USE) {
- printk("mpc.c: module in use\n");
- return;
- }
+ extern struct atm_mpoa_ops atm_mpoa_ops;
+ struct mpoa_client *mpc, *tmp;
+ struct atm_mpoa_qos *qos, *nextqos;
+ struct lec_priv *priv;
+
+ if (MOD_IN_USE) {
+ printk("mpc.c: module in use\n");
+ return;
+ }
#ifdef CONFIG_PROC_FS
mpc_proc_clean();
#endif
- del_timer(&mpc_timer);
- unregister_netdevice_notifier(&mpoa_notifier);
- atm_mpoa_ops.mpoad_attach = NULL;
- atm_mpoa_ops.vcc_attach = NULL;
-
- mpc = mpcs;
- mpcs = NULL;
- while (mpc != NULL) {
- tmp = mpc->next;
- if (mpc->dev != NULL) {
- stop_mpc(mpc);
- priv = (struct lec_priv *)mpc->dev->priv;
- if (priv->lane2_ops != NULL)
- priv->lane2_ops->associate_indicator = NULL;
- }
- ddprintk("mpoa: cleanup_module: about to clear caches\n");
- while(mpc->in_ops->cache_remove(mpc->in_cache, mpc));
- while(mpc->eg_ops->cache_remove(mpc->eg_cache, mpc));
- ddprintk("mpoa: cleanup_module: caches cleared\n");
- kfree(mpc->mps_macs);
- memset(mpc, 0, sizeof(struct mpoa_client));
- ddprintk("mpoa: cleanup_module: about to kfree %p\n", mpc);
- kfree(mpc);
- ddprintk("mpoa: cleanup_module: next mpc is at %p\n", tmp);
- mpc = tmp;
- }
-
- qos = qos_head;
- qos_head = NULL;
- while (qos != NULL) {
- nextqos = qos->next;
- dprintk("mpoa: cleanup_module: freeing qos entry %p\n", qos);
- kfree(qos);
- qos = nextqos;
- }
-
- return;
+ del_timer(&mpc_timer);
+ unregister_netdevice_notifier(&mpoa_notifier);
+ atm_mpoa_ops.mpoad_attach = NULL;
+ atm_mpoa_ops.vcc_attach = NULL;
+
+ mpc = mpcs;
+ mpcs = NULL;
+ while (mpc != NULL) {
+ tmp = mpc->next;
+ if (mpc->dev != NULL) {
+ stop_mpc(mpc);
+ priv = (struct lec_priv *)mpc->dev->priv;
+ if (priv->lane2_ops != NULL)
+ priv->lane2_ops->associate_indicator = NULL;
+ }
+ ddprintk("mpoa: cleanup_module: about to clear caches\n");
+ mpc->in_ops->destroy_cache(mpc);
+ mpc->eg_ops->destroy_cache(mpc);
+ ddprintk("mpoa: cleanup_module: caches cleared\n");
+ kfree(mpc->mps_macs);
+ memset(mpc, 0, sizeof(struct mpoa_client));
+ ddprintk("mpoa: cleanup_module: about to kfree %p\n", mpc);
+ kfree(mpc);
+ ddprintk("mpoa: cleanup_module: next mpc is at %p\n", tmp);
+ mpc = tmp;
+ }
+
+ qos = qos_head;
+ qos_head = NULL;
+ while (qos != NULL) {
+ nextqos = qos->next;
+ dprintk("mpoa: cleanup_module: freeing qos entry %p\n", qos);
+ kfree(qos);
+ qos = nextqos;
+ }
+
+ return;
}
#endif /* MODULE */
diff --git a/net/atm/mpoa_caches.c b/net/atm/mpoa_caches.c
index 8b94fb055..0bca7aa6c 100644
--- a/net/atm/mpoa_caches.c
+++ b/net/atm/mpoa_caches.c
@@ -22,165 +22,159 @@
#define ddprintk(format,args...)
#endif
-static in_cache_entry *in_cache_search(uint32_t dst_ip,
- struct mpoa_client *client)
+static in_cache_entry *in_cache_get(uint32_t dst_ip,
+ struct mpoa_client *client)
{
- unsigned long flags;
- in_cache_entry *entry;
-
- read_lock_irqsave(&client->ingress_lock, flags);
- entry = client->in_cache;
- while(entry != NULL){
- if( entry->ctrl_info.in_dst_ip == dst_ip ){
- read_unlock_irqrestore(&client->ingress_lock, flags);
- return entry;
- }
- entry = entry->next;
- }
- read_unlock_irqrestore(&client->ingress_lock, flags);
-
- return NULL;
+ in_cache_entry *entry;
+
+ read_lock_bh(&client->ingress_lock);
+ entry = client->in_cache;
+ while(entry != NULL){
+ if( entry->ctrl_info.in_dst_ip == dst_ip ){
+ atomic_inc(&entry->use);
+ read_unlock_bh(&client->ingress_lock);
+ return entry;
+ }
+ entry = entry->next;
+ }
+ read_unlock_bh(&client->ingress_lock);
+
+ return NULL;
}
-static in_cache_entry *in_cache_search_with_mask(uint32_t dst_ip,
- struct mpoa_client *client,
- uint32_t mask){
- unsigned long flags;
- in_cache_entry *entry;
-
- read_lock_irqsave(&client->ingress_lock, flags);
- entry = client->in_cache;
- while(entry != NULL){
- if((entry->ctrl_info.in_dst_ip & mask) == (dst_ip & mask )){
- read_unlock_irqrestore(&client->ingress_lock, flags);
- return entry;
- }
- entry = entry->next;
- }
- read_unlock_irqrestore(&client->ingress_lock, flags);
-
- return NULL;
-
+static in_cache_entry *in_cache_get_with_mask(uint32_t dst_ip,
+ struct mpoa_client *client,
+ uint32_t mask)
+{
+ in_cache_entry *entry;
+
+ read_lock_bh(&client->ingress_lock);
+ entry = client->in_cache;
+ while(entry != NULL){
+ if((entry->ctrl_info.in_dst_ip & mask) == (dst_ip & mask )){
+ atomic_inc(&entry->use);
+ read_unlock_bh(&client->ingress_lock);
+ return entry;
+ }
+ entry = entry->next;
+ }
+ read_unlock_bh(&client->ingress_lock);
+
+ return NULL;
+
}
-static in_cache_entry *in_cache_search_by_vcc(struct atm_vcc *vcc,
- struct mpoa_client *client )
+static in_cache_entry *in_cache_get_by_vcc(struct atm_vcc *vcc,
+ struct mpoa_client *client )
{
- unsigned long flags;
- in_cache_entry *entry;
-
- read_lock_irqsave(&client->ingress_lock, flags);
- entry = client->in_cache;
- while(entry != NULL){
- if(entry->shortcut == vcc) {
- read_unlock_irqrestore(&client->ingress_lock, flags);
- return entry;
- }
+ in_cache_entry *entry;
+
+ read_lock_bh(&client->ingress_lock);
+ entry = client->in_cache;
+ while(entry != NULL){
+ if(entry->shortcut == vcc) {
+ atomic_inc(&entry->use);
+ read_unlock_bh(&client->ingress_lock);
+ return entry;
+ }
entry = entry->next;
- }
- read_unlock_irqrestore(&client->ingress_lock, flags);
+ }
+ read_unlock_bh(&client->ingress_lock);
- return NULL;
+ return NULL;
}
-static in_cache_entry *new_in_cache_entry(uint32_t dst_ip,
+static in_cache_entry *in_cache_add_entry(uint32_t dst_ip,
struct mpoa_client *client)
{
- unsigned long flags;
- unsigned char *ip __attribute__ ((unused)) = (unsigned char *)&dst_ip;
- in_cache_entry* entry = kmalloc(sizeof(in_cache_entry), GFP_KERNEL);
-
- if (entry == NULL) {
- printk("mpoa: mpoa_caches.c: new_in_cache_entry: out of memory\n");
- return NULL;
- }
-
- dprintk("mpoa: mpoa_caches.c: adding an ingress entry, ip = %u.%u.%u.%u\n", ip[0], ip[1], ip[2], ip[3]);
- memset(entry,0,sizeof(in_cache_entry));
-
- dprintk("mpoa: mpoa_caches.c: new_in_cache_entry: about to lock\n");
- write_lock_irqsave(&client->ingress_lock, flags);
- entry->next = client->in_cache;
- entry->prev = NULL;
- if (client->in_cache != NULL)
- client->in_cache->prev = entry;
- client->in_cache = entry;
- write_unlock_irqrestore(&client->ingress_lock, flags);
- dprintk("mpoa: mpoa_caches.c: new_in_cache_entry: unlocked\n");
-
- memcpy(entry->MPS_ctrl_ATM_addr, client->mps_ctrl_addr, ATM_ESA_LEN);
- entry->ctrl_info.in_dst_ip = dst_ip;
- do_gettimeofday(&(entry->tv));
- entry->retry_time = client->parameters.mpc_p4;
- entry->count = 1;
- entry->entry_state = INGRESS_INVALID;
- entry->ctrl_info.holding_time = HOLDING_TIME_DEFAULT;
+ unsigned char *ip __attribute__ ((unused)) = (unsigned char *)&dst_ip;
+ in_cache_entry* entry = kmalloc(sizeof(in_cache_entry), GFP_KERNEL);
+
+ if (entry == NULL) {
+ printk("mpoa: mpoa_caches.c: new_in_cache_entry: out of memory\n");
+ return NULL;
+ }
+
+ dprintk("mpoa: mpoa_caches.c: adding an ingress entry, ip = %u.%u.%u.%u\n", ip[0], ip[1], ip[2], ip[3]);
+ memset(entry,0,sizeof(in_cache_entry));
+
+ atomic_set(&entry->use, 1);
+ dprintk("mpoa: mpoa_caches.c: new_in_cache_entry: about to lock\n");
+ write_lock_bh(&client->ingress_lock);
+ entry->next = client->in_cache;
+ entry->prev = NULL;
+ if (client->in_cache != NULL)
+ client->in_cache->prev = entry;
+ client->in_cache = entry;
+
+ memcpy(entry->MPS_ctrl_ATM_addr, client->mps_ctrl_addr, ATM_ESA_LEN);
+ entry->ctrl_info.in_dst_ip = dst_ip;
+ do_gettimeofday(&(entry->tv));
+ entry->retry_time = client->parameters.mpc_p4;
+ entry->count = 1;
+ entry->entry_state = INGRESS_INVALID;
+ entry->ctrl_info.holding_time = HOLDING_TIME_DEFAULT;
+ atomic_inc(&entry->use);
+
+ write_unlock_bh(&client->ingress_lock);
+ dprintk("mpoa: mpoa_caches.c: new_in_cache_entry: unlocked\n");
return entry;
}
-static int cache_hit( in_cache_entry * entry, struct mpoa_client *mpc)
+static int cache_hit(in_cache_entry *entry, struct mpoa_client *mpc)
{
- struct atm_mpoa_qos *qos;
- struct k_message msg;
+ struct atm_mpoa_qos *qos;
+ struct k_message msg;
- entry->count++;
+ entry->count++;
if(entry->entry_state == INGRESS_RESOLVED && entry->shortcut != NULL)
- return OPEN;
+ return OPEN;
if(entry->entry_state == INGRESS_REFRESHING){
- if(entry->count > mpc->parameters.mpc_p1){
- msg.type = SND_MPOA_RES_RQST;
+ if(entry->count > mpc->parameters.mpc_p1){
+ msg.type = SND_MPOA_RES_RQST;
msg.content.in_info = entry->ctrl_info;
memcpy(msg.MPS_ctrl, mpc->mps_ctrl_addr, ATM_ESA_LEN);
- qos = atm_mpoa_search_qos(entry->ctrl_info.in_dst_ip);
- if (qos != NULL) msg.qos = qos->qos;
+ qos = atm_mpoa_search_qos(entry->ctrl_info.in_dst_ip);
+ if (qos != NULL) msg.qos = qos->qos;
msg_to_mpoad(&msg, mpc);
do_gettimeofday(&(entry->reply_wait));
entry->entry_state = INGRESS_RESOLVING;
}
if(entry->shortcut != NULL)
- return OPEN;
+ return OPEN;
return CLOSED;
}
- if(entry->entry_state == INGRESS_RESOLVING && entry->shortcut != NULL)
- return OPEN;
+ if(entry->entry_state == INGRESS_RESOLVING && entry->shortcut != NULL)
+ return OPEN;
- if( entry->count > mpc->parameters.mpc_p1 &&
- entry->entry_state == INGRESS_INVALID){
- unsigned char *ip __attribute__ ((unused)) =
+ if( entry->count > mpc->parameters.mpc_p1 &&
+ entry->entry_state == INGRESS_INVALID){
+ unsigned char *ip __attribute__ ((unused)) =
(unsigned char *)&entry->ctrl_info.in_dst_ip;
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]);
- entry->entry_state = INGRESS_RESOLVING;
- msg.type = SND_MPOA_RES_RQST;
- memcpy(msg.MPS_ctrl, mpc->mps_ctrl_addr, ATM_ESA_LEN );
- msg.content.in_info = entry->ctrl_info;
- qos = atm_mpoa_search_qos(entry->ctrl_info.in_dst_ip);
- if (qos != NULL) msg.qos = qos->qos;
- msg_to_mpoad( &msg, mpc);
- do_gettimeofday(&(entry->reply_wait));
- }
-
- return CLOSED;
+ entry->entry_state = INGRESS_RESOLVING;
+ msg.type = SND_MPOA_RES_RQST;
+ memcpy(msg.MPS_ctrl, mpc->mps_ctrl_addr, ATM_ESA_LEN );
+ msg.content.in_info = entry->ctrl_info;
+ qos = atm_mpoa_search_qos(entry->ctrl_info.in_dst_ip);
+ if (qos != NULL) msg.qos = qos->qos;
+ msg_to_mpoad( &msg, mpc);
+ do_gettimeofday(&(entry->reply_wait));
+ }
+
+ return CLOSED;
}
-/*
- * If there are no more references to vcc in egress cache,
- * we are ready to close it.
- */
-static void close_unused_egress_vcc(struct atm_vcc *vcc, struct mpoa_client *mpc)
+static void in_cache_put(in_cache_entry *entry)
{
- if (vcc == NULL)
- return;
-
- dprintk("mpoa: mpoa_caches.c: close_unused_egress_vcc:\n");
- if (mpc->eg_ops->search_by_vcc(vcc, mpc) != NULL)
- return; /* entry still in use */
-
- atm_async_release_vcc(vcc, -EPIPE); /* nobody uses this VCC anymore, close it */
- dprintk("mpoa: mpoa_caches.c: close_unused_egress_vcc, closed one:\n");
+ if (atomic_dec_and_test(&entry->use)) {
+ memset(entry, 0, sizeof(in_cache_entry));
+ kfree(entry);
+ }
return;
}
@@ -188,371 +182,395 @@ static void close_unused_egress_vcc(struct atm_vcc *vcc, struct mpoa_client *mpc
/*
* This should be called with write lock on
*/
-static int in_cache_remove( in_cache_entry *entry,
- struct mpoa_client *client )
+static void in_cache_remove_entry(in_cache_entry *entry,
+ struct mpoa_client *client)
{
struct atm_vcc *vcc;
- struct k_message msg;
- unsigned char *ip;
-
- if(entry == NULL)
- return 0;
+ struct k_message msg;
+ unsigned char *ip;
vcc = entry->shortcut;
- ip = (unsigned char *)&entry->ctrl_info.in_dst_ip;
- dprintk("mpoa: mpoa_caches.c: removing an ingress entry, ip = %u.%u.%u.%u\n",ip[0], ip[1], ip[2], ip[3]);
-
- if (entry->prev != NULL)
- entry->prev->next = entry->next;
- else
- client->in_cache = entry->next;
- if (entry->next != NULL)
- entry->next->prev = entry->prev;
- memset(entry, 0, sizeof(in_cache_entry));
- kfree(entry);
+ ip = (unsigned char *)&entry->ctrl_info.in_dst_ip;
+ dprintk("mpoa: mpoa_caches.c: removing an ingress entry, ip = %u.%u.%u.%u\n",ip[0], ip[1], ip[2], ip[3]);
+
+ if (entry->prev != NULL)
+ entry->prev->next = entry->next;
+ else
+ client->in_cache = entry->next;
+ if (entry->next != NULL)
+ entry->next->prev = entry->prev;
+ client->in_ops->put(entry);
if(client->in_cache == NULL && client->eg_cache == NULL){
- msg.type = STOP_KEEP_ALIVE_SM;
+ msg.type = STOP_KEEP_ALIVE_SM;
msg_to_mpoad(&msg,client);
}
- close_unused_egress_vcc(vcc, client);
- return 1;
-}
+ /* Check if the egress side still uses this VCC */
+ if (vcc != NULL) {
+ eg_cache_entry *eg_entry = client->eg_ops->get_by_vcc(vcc, client);
+ if (eg_entry != NULL) {
+ client->eg_ops->put(eg_entry);
+ return;
+ }
+ atm_async_release_vcc(vcc, -EPIPE);
+ }
+ return;
+}
-/* Call this every MPC-p2 seconds... Not exactly correct solution,
- but an easy one... */
+/* Call this every MPC-p2 seconds... Not exactly correct solution,
+ but an easy one... */
static void clear_count_and_expired(struct mpoa_client *client)
{
- unsigned char *ip;
- unsigned long flags;
- in_cache_entry *entry, *next_entry;
- struct timeval now;
+ unsigned char *ip;
+ in_cache_entry *entry, *next_entry;
+ struct timeval now;
do_gettimeofday(&now);
-
- write_lock_irqsave(&client->ingress_lock, flags);
- entry = client->in_cache;
- while(entry != NULL){
- entry->count=0;
- next_entry = entry->next;
- if((now.tv_sec - entry->tv.tv_sec)
- > entry->ctrl_info.holding_time){
- ip = (unsigned char*)&entry->ctrl_info.in_dst_ip;
- dprintk("mpoa: mpoa_caches.c: holding time expired, ip = %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]);
- in_cache_remove(entry, client);
- }
- entry = next_entry;
- }
- write_unlock_irqrestore(&client->ingress_lock, flags);
-
- return;
-}
-/* Call this every MPC-p4 seconds. */
+ write_lock_bh(&client->ingress_lock);
+ entry = client->in_cache;
+ while(entry != NULL){
+ entry->count=0;
+ next_entry = entry->next;
+ if((now.tv_sec - entry->tv.tv_sec)
+ > entry->ctrl_info.holding_time){
+ ip = (unsigned char*)&entry->ctrl_info.in_dst_ip;
+ dprintk("mpoa: mpoa_caches.c: holding time expired, ip = %u.%u.%u.%u\n", NIPQUAD(ip));
+ client->in_ops->remove_entry(entry, client);
+ }
+ entry = next_entry;
+ }
+ write_unlock_bh(&client->ingress_lock);
+
+ return;
+}
-static void check_resolving_entries( struct mpoa_client * client )
+/* Call this every MPC-p4 seconds. */
+static void check_resolving_entries(struct mpoa_client *client)
{
- struct atm_mpoa_qos *qos;
- unsigned long flags;
- in_cache_entry *entry;
- struct timeval now;
- struct k_message msg;
+ struct atm_mpoa_qos *qos;
+ in_cache_entry *entry;
+ struct timeval now;
+ struct k_message msg;
do_gettimeofday( &now );
- read_lock_irqsave(&client->ingress_lock, flags);
- entry = client->in_cache;
- while( entry != NULL ){
- if(entry->entry_state == INGRESS_RESOLVING){
- if(now.tv_sec - entry->hold_down.tv_sec < client->parameters.mpc_p6){
- entry = entry->next; /* Entry in hold down */
- continue;
- }
- if( (now.tv_sec - entry->reply_wait.tv_sec) >
- entry->retry_time ){
- entry->retry_time = MPC_C1*( entry->retry_time );
- if(entry->retry_time > client->parameters.mpc_p5){
- /* Retry time maximum exceeded, put entry in hold down. */
- do_gettimeofday(&(entry->hold_down));
- entry->retry_time = client->parameters.mpc_p4;
- entry = entry->next;
- continue;
- }
+ read_lock_bh(&client->ingress_lock);
+ entry = client->in_cache;
+ while( entry != NULL ){
+ if(entry->entry_state == INGRESS_RESOLVING){
+ if(now.tv_sec - entry->hold_down.tv_sec < client->parameters.mpc_p6){
+ entry = entry->next; /* Entry in hold down */
+ continue;
+ }
+ if( (now.tv_sec - entry->reply_wait.tv_sec) >
+ entry->retry_time ){
+ entry->retry_time = MPC_C1*( entry->retry_time );
+ if(entry->retry_time > client->parameters.mpc_p5){
+ /* Retry time maximum exceeded, put entry in hold down. */
+ do_gettimeofday(&(entry->hold_down));
+ entry->retry_time = client->parameters.mpc_p4;
+ entry = entry->next;
+ continue;
+ }
/* Ask daemon to send a resolution request. */
- memset(&(entry->hold_down),0,sizeof(struct timeval));
- msg.type = SND_MPOA_RES_RTRY;
- memcpy(msg.MPS_ctrl, client->mps_ctrl_addr, ATM_ESA_LEN);
- msg.content.in_info = entry->ctrl_info;
- qos = atm_mpoa_search_qos(entry->ctrl_info.in_dst_ip);
- if (qos != NULL) msg.qos = qos->qos;
- msg_to_mpoad(&msg, client);
- do_gettimeofday(&(entry->reply_wait));
- }
- }
- entry = entry->next;
- }
- read_unlock_irqrestore(&client->ingress_lock, flags);
+ memset(&(entry->hold_down),0,sizeof(struct timeval));
+ msg.type = SND_MPOA_RES_RTRY;
+ memcpy(msg.MPS_ctrl, client->mps_ctrl_addr, ATM_ESA_LEN);
+ msg.content.in_info = entry->ctrl_info;
+ qos = atm_mpoa_search_qos(entry->ctrl_info.in_dst_ip);
+ if (qos != NULL) msg.qos = qos->qos;
+ msg_to_mpoad(&msg, client);
+ do_gettimeofday(&(entry->reply_wait));
+ }
+ }
+ entry = entry->next;
+ }
+ read_unlock_bh(&client->ingress_lock);
}
/* Call this every MPC-p5 seconds. */
-
-static void refresh_entries( struct mpoa_client * client )
+static void refresh_entries(struct mpoa_client *client)
{
- unsigned long flags;
- struct timeval now;
- struct in_cache_entry *entry = client->in_cache;
-
- ddprintk("mpoa: mpoa_caches.c: refresh_entries\n");
+ struct timeval now;
+ struct in_cache_entry *entry = client->in_cache;
+
+ ddprintk("mpoa: mpoa_caches.c: refresh_entries\n");
do_gettimeofday(&now);
- read_lock_irqsave(&client->ingress_lock, flags);
- while( entry != NULL ){
- if( entry->entry_state == INGRESS_RESOLVED ){
- if(!(entry->refresh_time))
- entry->refresh_time = (2*(entry->ctrl_info.holding_time))/3;
+ read_lock_bh(&client->ingress_lock);
+ while( entry != NULL ){
+ if( entry->entry_state == INGRESS_RESOLVED ){
+ if(!(entry->refresh_time))
+ entry->refresh_time = (2*(entry->ctrl_info.holding_time))/3;
if( (now.tv_sec - entry->reply_wait.tv_sec) > entry->refresh_time ){
- dprintk("mpoa: mpoa_caches.c: refreshing an entry.\n");
+ dprintk("mpoa: mpoa_caches.c: refreshing an entry.\n");
entry->entry_state = INGRESS_REFRESHING;
-
+
}
- }
- entry = entry->next;
- }
- read_unlock_irqrestore(&client->ingress_lock, flags);
+ }
+ entry = entry->next;
+ }
+ read_unlock_bh(&client->ingress_lock);
}
-static eg_cache_entry *eg_cache_search_by_cache_id(uint32_t cache_id,
- struct mpoa_client *client)
+static void in_destroy_cache(struct mpoa_client *mpc)
{
- eg_cache_entry *entry;
- unsigned long flags;
-
- read_lock_irqsave(&client->egress_lock, flags);
- entry = client->eg_cache;
- while(entry != NULL){
- if( entry->ctrl_info.cache_id == cache_id){
- read_unlock_irqrestore(&client->egress_lock, flags);
- return entry;
- }
- entry = entry->next;
- }
- read_unlock_irqrestore(&client->egress_lock, flags);
-
- return NULL;
+ write_lock_irq(&mpc->ingress_lock);
+ while(mpc->in_cache != NULL)
+ mpc->in_ops->remove_entry(mpc->in_cache, mpc);
+ write_unlock_irq(&mpc->ingress_lock);
+
+ return;
}
-static eg_cache_entry *eg_cache_search_by_tag(uint32_t tag,
- struct mpoa_client *client)
+static eg_cache_entry *eg_cache_get_by_cache_id(uint32_t cache_id, struct mpoa_client *mpc)
{
- unsigned long flags;
- eg_cache_entry *entry;
-
- read_lock_irqsave(&client->egress_lock, flags);
- entry = client->eg_cache;
- while(entry != NULL){
- if( entry->ctrl_info.tag == tag){
- read_unlock_irqrestore(&client->egress_lock, flags);
- return entry;
- }
- entry = entry->next;
- }
- read_unlock_irqrestore(&client->egress_lock, flags);
-
- return NULL;
+ eg_cache_entry *entry;
+
+ read_lock_irq(&mpc->egress_lock);
+ entry = mpc->eg_cache;
+ while(entry != NULL){
+ if(entry->ctrl_info.cache_id == cache_id){
+ atomic_inc(&entry->use);
+ read_unlock_irq(&mpc->egress_lock);
+ return entry;
+ }
+ entry = entry->next;
+ }
+ read_unlock_irq(&mpc->egress_lock);
+
+ return NULL;
}
-static eg_cache_entry *eg_cache_search_by_vcc(struct atm_vcc *vcc,
- struct mpoa_client *client )
+/* This can be called from any context since it saves CPU flags */
+static eg_cache_entry *eg_cache_get_by_tag(uint32_t tag, struct mpoa_client *mpc)
{
- unsigned long flags;
- eg_cache_entry *entry;
-
- read_lock_irqsave(&client->egress_lock, flags);
- entry = client->eg_cache;
- while( entry != NULL ){
- if( entry->shortcut == vcc ) {
- read_unlock_irqrestore(&client->egress_lock, flags);
- return entry;
+ unsigned long flags;
+ eg_cache_entry *entry;
+
+ read_lock_irqsave(&mpc->egress_lock, flags);
+ entry = mpc->eg_cache;
+ while (entry != NULL){
+ if (entry->ctrl_info.tag == tag) {
+ atomic_inc(&entry->use);
+ read_unlock_irqrestore(&mpc->egress_lock, flags);
+ return entry;
}
- entry = entry->next;
- }
- read_unlock_irqrestore(&client->egress_lock, flags);
+ entry = entry->next;
+ }
+ read_unlock_irqrestore(&mpc->egress_lock, flags);
- return NULL;
+ return NULL;
}
-static eg_cache_entry *eg_cache_search_by_src_ip(uint32_t ipaddr,
- struct mpoa_client *client)
+/* This can be called from any context since it saves CPU flags */
+static eg_cache_entry *eg_cache_get_by_vcc(struct atm_vcc *vcc, struct mpoa_client *mpc)
{
- unsigned long flags;
- eg_cache_entry *entry;
-
- read_lock_irqsave(&client->egress_lock, flags);
- entry = client->eg_cache;
- while( entry != NULL ){
- if(entry->latest_ip_addr == ipaddr) {
- break;
+ unsigned long flags;
+ eg_cache_entry *entry;
+
+ read_lock_irqsave(&mpc->egress_lock, flags);
+ entry = mpc->eg_cache;
+ while (entry != NULL){
+ if (entry->shortcut == vcc) {
+ atomic_inc(&entry->use);
+ read_unlock_irqrestore(&mpc->egress_lock, flags);
+ return entry;
}
- entry = entry->next;
- }
- read_unlock_irqrestore(&client->egress_lock, flags);
+ entry = entry->next;
+ }
+ read_unlock_irqrestore(&mpc->egress_lock, flags);
- return entry;
+ return NULL;
}
-/*
- * If there are no more references to vcc in ingress cache,
- * we are ready to close it.
- */
-static void close_unused_ingress_vcc(struct atm_vcc *vcc, struct mpoa_client *mpc)
+static eg_cache_entry *eg_cache_get_by_src_ip(uint32_t ipaddr, struct mpoa_client *mpc)
{
- if (vcc == NULL)
- return;
+ eg_cache_entry *entry;
+
+ read_lock_irq(&mpc->egress_lock);
+ entry = mpc->eg_cache;
+ while(entry != NULL){
+ if(entry->latest_ip_addr == ipaddr) {
+ atomic_inc(&entry->use);
+ read_unlock_irq(&mpc->egress_lock);
+ return entry;
+ }
+ entry = entry->next;
+ }
+ read_unlock_irq(&mpc->egress_lock);
- dprintk("mpoa: mpoa_caches.c: close_unused_ingress_vcc:\n");
- if (mpc->in_ops->search_by_vcc(vcc, mpc) != NULL)
- return; /* entry still in use */
+ return NULL;
+}
- atm_async_release_vcc(vcc, -EPIPE); /* nobody uses this VCC anymore, close it */
- dprintk("mpoa: mpoa_caches.c: close_unused_ingress_vcc:, closed one\n");
+static void eg_cache_put(eg_cache_entry *entry)
+{
+ if (atomic_dec_and_test(&entry->use)) {
+ memset(entry, 0, sizeof(eg_cache_entry));
+ kfree(entry);
+ }
return;
}
+
/*
* This should be called with write lock on
*/
-static int eg_cache_remove(eg_cache_entry *entry,
- struct mpoa_client *client)
+static void eg_cache_remove_entry(eg_cache_entry *entry,
+ struct mpoa_client *client)
{
struct atm_vcc *vcc;
- struct k_message msg;
- if(entry == NULL)
- return 0;
+ struct k_message msg;
vcc = entry->shortcut;
- dprintk("mpoa: mpoa_caches.c: removing an egress entry.\n");
- if (entry->prev != NULL)
- entry->prev->next = entry->next;
- else
- client->eg_cache = entry->next;
- if (entry->next != NULL)
- entry->next->prev = entry->prev;
- memset(entry, 0, sizeof(eg_cache_entry));
- kfree(entry);
+ dprintk("mpoa: mpoa_caches.c: removing an egress entry.\n");
+ if (entry->prev != NULL)
+ entry->prev->next = entry->next;
+ else
+ client->eg_cache = entry->next;
+ if (entry->next != NULL)
+ entry->next->prev = entry->prev;
+ client->eg_ops->put(entry);
if(client->in_cache == NULL && client->eg_cache == NULL){
- msg.type = STOP_KEEP_ALIVE_SM;
+ msg.type = STOP_KEEP_ALIVE_SM;
msg_to_mpoad(&msg,client);
}
- close_unused_ingress_vcc(vcc, client);
+ /* Check if the ingress side still uses this VCC */
+ if (vcc != NULL) {
+ in_cache_entry *in_entry = client->in_ops->get_by_vcc(vcc, client);
+ if (in_entry != NULL) {
+ client->in_ops->put(in_entry);
+ return;
+ }
+ atm_async_release_vcc(vcc, -EPIPE);
+ }
- return 1;
-}
+ return;
+}
-static eg_cache_entry *new_eg_cache_entry(struct k_message *msg, struct mpoa_client *client)
+static eg_cache_entry *eg_cache_add_entry(struct k_message *msg, struct mpoa_client *client)
{
- unsigned long flags;
- unsigned char *ip;
- eg_cache_entry *entry = kmalloc(sizeof(eg_cache_entry), GFP_KERNEL);
+ unsigned char *ip;
+ eg_cache_entry *entry = kmalloc(sizeof(eg_cache_entry), GFP_KERNEL);
- if (entry == NULL) {
- printk("mpoa: mpoa_caches.c: new_eg_cache_entry: out of memory\n");
- return NULL;
+ if (entry == NULL) {
+ printk("mpoa: mpoa_caches.c: new_eg_cache_entry: out of memory\n");
+ return NULL;
}
- ip = (unsigned char *)&msg->content.eg_info.eg_dst_ip;
- dprintk("mpoa: mpoa_caches.c: adding an egress entry, ip = %d.%d.%d.%d, this should be our IP\n", ip[0], ip[1], ip[2], ip[3]);
- memset(entry, 0, sizeof(eg_cache_entry));
-
- dprintk("mpoa: mpoa_caches.c: new_eg_cache_entry: about to lock\n");
- write_lock_irqsave(&client->egress_lock, flags);
- entry->next = client->eg_cache;
- entry->prev = NULL;
- if (client->eg_cache != NULL)
- client->eg_cache->prev = entry;
- client->eg_cache = entry;
- write_unlock_irqrestore(&client->egress_lock, flags);
- dprintk("mpoa: mpoa_caches.c: new_eg_cache_entry: unlocked\n");
-
- memcpy(entry->MPS_ctrl_ATM_addr, client->mps_ctrl_addr, ATM_ESA_LEN);
- entry->ctrl_info = msg->content.eg_info;
- do_gettimeofday(&(entry->tv));
- entry->entry_state = EGRESS_RESOLVED;
- dprintk("mpoa: mpoa_caches.c: new_eg_cache_entry cache_id %lu\n", ntohl(entry->ctrl_info.cache_id));
- ip = (unsigned char *)&entry->ctrl_info.mps_ip;
- dprintk("mpoa: mpoa_caches.c: mps_ip = %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]);
- return entry;
+ ip = (unsigned char *)&msg->content.eg_info.eg_dst_ip;
+ dprintk("mpoa: mpoa_caches.c: adding an egress entry, ip = %u.%u.%u.%u, this should be our IP\n", NIPQUAD(ip));
+ memset(entry, 0, sizeof(eg_cache_entry));
+
+ atomic_set(&entry->use, 1);
+ dprintk("mpoa: mpoa_caches.c: new_eg_cache_entry: about to lock\n");
+ write_lock_irq(&client->egress_lock);
+ entry->next = client->eg_cache;
+ entry->prev = NULL;
+ if (client->eg_cache != NULL)
+ client->eg_cache->prev = entry;
+ client->eg_cache = entry;
+
+ memcpy(entry->MPS_ctrl_ATM_addr, client->mps_ctrl_addr, ATM_ESA_LEN);
+ entry->ctrl_info = msg->content.eg_info;
+ do_gettimeofday(&(entry->tv));
+ entry->entry_state = EGRESS_RESOLVED;
+ dprintk("mpoa: mpoa_caches.c: new_eg_cache_entry cache_id %lu\n", ntohl(entry->ctrl_info.cache_id));
+ ip = (unsigned char *)&entry->ctrl_info.mps_ip;
+ dprintk("mpoa: mpoa_caches.c: mps_ip = %u.%u.%u.%u\n", NIPQUAD(ip));
+ atomic_inc(&entry->use);
+
+ write_unlock_irq(&client->egress_lock);
+ dprintk("mpoa: mpoa_caches.c: new_eg_cache_entry: unlocked\n");
+
+ return entry;
}
static void update_eg_cache_entry(eg_cache_entry * entry, uint16_t holding_time)
{
- do_gettimeofday(&(entry->tv));
- entry->entry_state = EGRESS_RESOLVED;
- entry->ctrl_info.holding_time = holding_time;
+ do_gettimeofday(&(entry->tv));
+ entry->entry_state = EGRESS_RESOLVED;
+ entry->ctrl_info.holding_time = holding_time;
- return;
+ return;
}
-static void clear_expired(struct mpoa_client *client){
- eg_cache_entry *entry, *next_entry;
- unsigned long flags;
- struct timeval now;
+static void clear_expired(struct mpoa_client *client)
+{
+ eg_cache_entry *entry, *next_entry;
+ struct timeval now;
struct k_message msg;
- do_gettimeofday(&now);
+ do_gettimeofday(&now);
- write_lock_irqsave(&client->egress_lock, flags);
- entry = client->eg_cache;
- while(entry != NULL){
- next_entry = entry->next;
- if((now.tv_sec - entry->tv.tv_sec)
- > entry->ctrl_info.holding_time){
- msg.type = SND_EGRESS_PURGE;
+ write_lock_irq(&client->egress_lock);
+ entry = client->eg_cache;
+ while(entry != NULL){
+ next_entry = entry->next;
+ if((now.tv_sec - entry->tv.tv_sec)
+ > entry->ctrl_info.holding_time){
+ msg.type = SND_EGRESS_PURGE;
msg.content.eg_info = entry->ctrl_info;
- dprintk("mpoa: mpoa_caches.c: egress_cache: holding time expired, cache_id = %lu.\n",ntohl(entry->ctrl_info.cache_id));
+ dprintk("mpoa: mpoa_caches.c: egress_cache: holding time expired, cache_id = %lu.\n",ntohl(entry->ctrl_info.cache_id));
msg_to_mpoad(&msg, client);
- eg_cache_remove(entry, client);
- }
- entry = next_entry;
- }
- write_unlock_irqrestore(&client->egress_lock, flags);
+ client->eg_ops->remove_entry(entry, client);
+ }
+ entry = next_entry;
+ }
+ write_unlock_irq(&client->egress_lock);
+
+ return;
+}
+
+static void eg_destroy_cache(struct mpoa_client *mpc)
+{
+ write_lock_irq(&mpc->egress_lock);
+ while(mpc->eg_cache != NULL)
+ mpc->eg_ops->remove_entry(mpc->eg_cache, mpc);
+ write_unlock_irq(&mpc->egress_lock);
- return;
+ return;
}
static struct in_cache_ops ingress_ops = {
- new_in_cache_entry, /* new_entry */
- in_cache_search, /* search */
- in_cache_search_with_mask, /* search_with_mask */
- in_cache_search_by_vcc, /* search_by_vcc */
- cache_hit, /* cache_hit */
- in_cache_remove, /* cache_remove */
- clear_count_and_expired, /* clear_count */
- check_resolving_entries, /* check_resolving */
- refresh_entries, /* refresh */
+ in_cache_add_entry, /* add_entry */
+ in_cache_get, /* get */
+ in_cache_get_with_mask, /* get_with_mask */
+ in_cache_get_by_vcc, /* get_by_vcc */
+ in_cache_put, /* put */
+ in_cache_remove_entry, /* remove_entry */
+ cache_hit, /* cache_hit */
+ clear_count_and_expired, /* clear_count */
+ check_resolving_entries, /* check_resolving */
+ refresh_entries, /* refresh */
+ in_destroy_cache /* destroy_cache */
};
static struct eg_cache_ops egress_ops = {
- new_eg_cache_entry, /* new_entry */
- eg_cache_search_by_cache_id, /* search_by_cache_id */
- eg_cache_search_by_tag, /* search_by_tag */
- eg_cache_search_by_vcc, /* search_by_vcc */
- eg_cache_search_by_src_ip, /* search_by_src_ip */
- eg_cache_remove, /* cache_remove */
- update_eg_cache_entry, /* update */
- clear_expired /* clear_expired */
+ eg_cache_add_entry, /* add_entry */
+ eg_cache_get_by_cache_id, /* get_by_cache_id */
+ eg_cache_get_by_tag, /* get_by_tag */
+ eg_cache_get_by_vcc, /* get_by_vcc */
+ eg_cache_get_by_src_ip, /* get_by_src_ip */
+ eg_cache_put, /* put */
+ eg_cache_remove_entry, /* remove_entry */
+ update_eg_cache_entry, /* update */
+ clear_expired, /* clear_expired */
+ eg_destroy_cache /* destroy_cache */
};
void atm_mpoa_init_cache(struct mpoa_client *mpc)
{
- mpc->in_ops = &ingress_ops;
- mpc->eg_ops = &egress_ops;
+ mpc->in_ops = &ingress_ops;
+ mpc->eg_ops = &egress_ops;
- return;
+ return;
}
diff --git a/net/atm/mpoa_caches.h b/net/atm/mpoa_caches.h
index cdcd6ac16..6c9886a03 100644
--- a/net/atm/mpoa_caches.h
+++ b/net/atm/mpoa_caches.h
@@ -25,24 +25,27 @@ typedef struct in_cache_entry {
struct atm_vcc *shortcut;
uint8_t MPS_ctrl_ATM_addr[ATM_ESA_LEN];
struct in_ctrl_info ctrl_info;
+ atomic_t use;
} in_cache_entry;
struct in_cache_ops{
- in_cache_entry *(*new_entry)(uint32_t dst_ip,
- struct mpoa_client *client);
- in_cache_entry *(*search)(uint32_t dst_ip, struct mpoa_client *client);
- in_cache_entry *(*search_with_mask)(uint32_t dst_ip,
- struct mpoa_client *client,
- uint32_t mask);
- in_cache_entry *(*search_by_vcc)(struct atm_vcc *vcc,
- struct mpoa_client *client);
- int (*cache_hit)(in_cache_entry *entry,
- struct mpoa_client *client);
- int (*cache_remove)(in_cache_entry *delEntry,
- struct mpoa_client *client );
- void (*clear_count)(struct mpoa_client *client);
- void (*check_resolving)(struct mpoa_client *client);
- void (*refresh)(struct mpoa_client *client);
+ in_cache_entry *(*add_entry)(uint32_t dst_ip,
+ struct mpoa_client *client);
+ in_cache_entry *(*get)(uint32_t dst_ip, struct mpoa_client *client);
+ in_cache_entry *(*get_with_mask)(uint32_t dst_ip,
+ struct mpoa_client *client,
+ uint32_t mask);
+ in_cache_entry *(*get_by_vcc)(struct atm_vcc *vcc,
+ struct mpoa_client *client);
+ void (*put)(in_cache_entry *entry);
+ void (*remove_entry)(in_cache_entry *delEntry,
+ struct mpoa_client *client );
+ int (*cache_hit)(in_cache_entry *entry,
+ struct mpoa_client *client);
+ void (*clear_count)(struct mpoa_client *client);
+ void (*check_resolving)(struct mpoa_client *client);
+ void (*refresh)(struct mpoa_client *client);
+ void (*destroy_cache)(struct mpoa_client *mpc);
};
typedef struct eg_cache_entry{
@@ -55,17 +58,20 @@ typedef struct eg_cache_entry{
uint16_t entry_state;
uint32_t latest_ip_addr; /* The src IP address of the last packet */
struct eg_ctrl_info ctrl_info;
+ atomic_t use;
} eg_cache_entry;
struct eg_cache_ops{
- eg_cache_entry *(*new_entry)(struct k_message *msg, struct mpoa_client *client);
- eg_cache_entry *(*search_by_cache_id)(uint32_t cache_id, struct mpoa_client *client);
- eg_cache_entry *(*search_by_tag)(uint32_t cache_id, struct mpoa_client *client);
- eg_cache_entry *(*search_by_vcc)(struct atm_vcc *vcc, struct mpoa_client *client);
- eg_cache_entry *(*search_by_src_ip)(uint32_t ipaddr, struct mpoa_client *client);
- int (*cache_remove)(eg_cache_entry *entry, struct mpoa_client *client);
- void (*update)(eg_cache_entry *entry, uint16_t holding_time);
- void (*clear_expired)(struct mpoa_client *client);
+ eg_cache_entry *(*add_entry)(struct k_message *msg, struct mpoa_client *client);
+ eg_cache_entry *(*get_by_cache_id)(uint32_t cache_id, struct mpoa_client *client);
+ eg_cache_entry *(*get_by_tag)(uint32_t cache_id, struct mpoa_client *client);
+ eg_cache_entry *(*get_by_vcc)(struct atm_vcc *vcc, struct mpoa_client *client);
+ eg_cache_entry *(*get_by_src_ip)(uint32_t ipaddr, struct mpoa_client *client);
+ void (*put)(eg_cache_entry *entry);
+ void (*remove_entry)(eg_cache_entry *entry, struct mpoa_client *client);
+ void (*update)(eg_cache_entry *entry, uint16_t holding_time);
+ void (*clear_expired)(struct mpoa_client *client);
+ void (*destroy_cache)(struct mpoa_client *mpc);
};
diff --git a/net/atm/pvc.c b/net/atm/pvc.c
index 2493f04aa..fc71c2435 100644
--- a/net/atm/pvc.c
+++ b/net/atm/pvc.c
@@ -78,23 +78,23 @@ static int pvc_getname(struct socket *sock,struct sockaddr *sockaddr,
static struct proto_ops SOCKOPS_WRAPPED(pvc_proto_ops) = {
- PF_ATMPVC,
- atm_release,
- pvc_bind,
- pvc_connect,
- sock_no_socketpair,
- sock_no_accept,
- pvc_getname,
- atm_poll,
- atm_ioctl,
- sock_no_listen,
- pvc_shutdown,
- atm_setsockopt,
- atm_getsockopt,
- sock_no_fcntl,
- atm_sendmsg,
- atm_recvmsg,
- sock_no_mmap
+ family: PF_ATMPVC,
+
+ release: atm_release,
+ bind: pvc_bind,
+ connect: pvc_connect,
+ socketpair: sock_no_socketpair,
+ accept: sock_no_accept,
+ getname: pvc_getname,
+ poll: atm_poll,
+ ioctl: atm_ioctl,
+ listen: sock_no_listen,
+ shutdown: pvc_shutdown,
+ setsockopt: atm_setsockopt,
+ getsockopt: atm_getsockopt,
+ sendmsg: atm_sendmsg,
+ recvmsg: atm_recvmsg,
+ mmap: sock_no_mmap,
};
diff --git a/net/atm/raw.c b/net/atm/raw.c
index 0899c9f93..738b2a7be 100644
--- a/net/atm/raw.c
+++ b/net/atm/raw.c
@@ -39,7 +39,7 @@ static void atm_pop_raw(struct atm_vcc *vcc,struct sk_buff *skb)
DPRINTK("APopR (%d) %d -= %d\n",vcc->vci,vcc->tx_inuse,skb->truesize);
atomic_sub(skb->truesize+ATM_PDU_OVHD,&vcc->tx_inuse);
dev_kfree_skb_any(skb);
- wake_up(&vcc->wsleep);
+ wake_up(&vcc->sleep);
}
diff --git a/net/atm/svc.c b/net/atm/svc.c
index 47b991557..70fa063cb 100644
--- a/net/atm/svc.c
+++ b/net/atm/svc.c
@@ -397,23 +397,23 @@ static int svc_getsockopt(struct socket *sock,int level,int optname,
static struct proto_ops SOCKOPS_WRAPPED(svc_proto_ops) = {
- PF_ATMSVC,
- svc_release,
- svc_bind,
- svc_connect,
- sock_no_socketpair,
- svc_accept,
- svc_getname,
- atm_poll,
- atm_ioctl,
- svc_listen,
- svc_shutdown,
- svc_setsockopt,
- svc_getsockopt,
- sock_no_fcntl,
- atm_sendmsg,
- atm_recvmsg,
- sock_no_mmap
+ family: PF_ATMSVC,
+
+ release: svc_release,
+ bind: svc_bind,
+ connect: svc_connect,
+ socketpair: sock_no_socketpair,
+ accept: svc_accept,
+ getname: svc_getname,
+ poll: atm_poll,
+ ioctl: atm_ioctl,
+ listen: svc_listen,
+ shutdown: svc_shutdown,
+ setsockopt: svc_setsockopt,
+ getsockopt: svc_getsockopt,
+ sendmsg: atm_sendmsg,
+ recvmsg: atm_recvmsg,
+ mmap: sock_no_mmap,
};
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index 949c2b3e9..d99065efe 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -1795,24 +1795,23 @@ static struct net_proto_family ax25_family_ops =
};
static struct proto_ops SOCKOPS_WRAPPED(ax25_proto_ops) = {
- PF_AX25,
-
- ax25_release,
- ax25_bind,
- ax25_connect,
- sock_no_socketpair,
- ax25_accept,
- ax25_getname,
- datagram_poll,
- ax25_ioctl,
- ax25_listen,
- ax25_shutdown,
- ax25_setsockopt,
- ax25_getsockopt,
- sock_no_fcntl,
- ax25_sendmsg,
- ax25_recvmsg,
- sock_no_mmap
+ family: PF_AX25,
+
+ release: ax25_release,
+ bind: ax25_bind,
+ connect: ax25_connect,
+ socketpair: sock_no_socketpair,
+ accept: ax25_accept,
+ getname: ax25_getname,
+ poll: datagram_poll,
+ ioctl: ax25_ioctl,
+ listen: ax25_listen,
+ shutdown: ax25_shutdown,
+ setsockopt: ax25_setsockopt,
+ getsockopt: ax25_getsockopt,
+ sendmsg: ax25_sendmsg,
+ recvmsg: ax25_recvmsg,
+ mmap: sock_no_mmap,
};
#include <linux/smp_lock.h>
diff --git a/net/bridge/br.c b/net/bridge/br.c
index 0195f3631..bbbd53a60 100644
--- a/net/bridge/br.c
+++ b/net/bridge/br.c
@@ -5,7 +5,7 @@
* Authors:
* Lennert Buytenhek <buytenh@gnu.org>
*
- * $Id: br.c,v 1.41 2000/03/24 01:33:36 davem Exp $
+ * $Id: br.c,v 1.42 2000/04/14 10:10:34 davem Exp $
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -45,10 +45,8 @@ static int __init br_init(void)
br_handle_frame_hook = br_handle_frame;
br_ioctl_hook = br_ioctl_deviceless_stub;
#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
- write_lock(&lane_bridge_hook_lock);
br_fdb_get_hook = br_fdb_get;
br_fdb_put_hook = br_fdb_put;
- write_unlock(&lane_bridge_hook_lock);
#endif
register_netdevice_notifier(&br_device_notifier);
@@ -71,10 +69,8 @@ static void __exit br_deinit(void)
br_call_ioctl_atomic(__br_clear_ioctl_hook);
net_call_rx_atomic(__br_clear_frame_hook);
#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
- write_lock(&lane_bridge_hook_lock);
br_fdb_get_hook = NULL;
br_fdb_put_hook = NULL;
- write_unlock(&lane_bridge_hook_lock);
#endif
}
diff --git a/net/core/dev.c b/net/core/dev.c
index 81a35e7a0..cb6b75d9f 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -181,7 +181,7 @@ int netdev_nit=0;
* dev_add_pack - add packet handler
* @pt: packet type declaration
*
- * Add a protocol handler to the networking stack. The passed packet_type
+ * Add a protocol handler to the networking stack. The passed &packet_type
* is linked into kernel lists and may not be freed until it has been
* removed from the kernel lists.
*/
@@ -217,7 +217,7 @@ void dev_add_pack(struct packet_type *pt)
* @pt: packet type declaration
*
* Remove a protocol handler that was previously added to the kernel
- * protocol handlers by dev_add_pack. The passed packet_type is removed
+ * protocol handlers by dev_add_pack(). The passed &packet_type is removed
* from the kernel lists and can be freed or reused once this function
* returns.
*/
@@ -260,9 +260,9 @@ void dev_remove_pack(struct packet_type *pt)
* __dev_get_by_name - find a device by its name
* @name: name to find
*
- * Find an interface by name. Must be called under rtnl semaphore
- * or dev_base_lock. If the name is found a pointer to the device
- * is returned. If the name is not found then NULL is returned. The
+ * Find an interface by name. Must be called under RTNL semaphore
+ * or @dev_base_lock. If the name is found a pointer to the device
+ * is returned. If the name is not found then %NULL is returned. The
* reference counters are not incremented so the caller must be
* careful with locks.
*/
@@ -286,7 +286,7 @@ struct net_device *__dev_get_by_name(const char *name)
* Find an interface by name. This can be called from any
* context and does its own locking. The returned handle has
* the usage count incremented and the caller must use dev_put() to
- * release it when it is no longer needed. NULL is returned if no
+ * release it when it is no longer needed. %NULL is returned if no
* matching device is found.
*/
@@ -336,11 +336,11 @@ int dev_get(const char *name)
* __dev_get_by_index - find a device by its ifindex
* @ifindex: index of device
*
- * Search for an interface by index. Returns NULL if the device
+ * Search for an interface by index. Returns %NULL if the device
* is not found or a pointer to the device. The device has not
* had its reference counter increased so the caller must be careful
- * about locking. The caller must hold either the rtnl semaphore
- * or dev_base_lock.
+ * about locking. The caller must hold either the RTNL semaphore
+ * or @dev_base_lock.
*/
struct net_device * __dev_get_by_index(int ifindex)
@@ -440,15 +440,15 @@ int dev_alloc_name(struct net_device *dev, const char *name)
* @name: name format string
* @err: error return pointer
*
- * Passed a format string - eg "lt%d" it will allocate a network device
- * and space for the name. NULL is returned if no memory is available.
+ * Passed a format string, eg. "lt%d", it will allocate a network device
+ * and space for the name. %NULL is returned if no memory is available.
* If the allocation succeeds then the name is assigned and the
- * device pointer returned. NULL is returned if the name allocation failed.
- * The cause of an error is returned as a negative errno code in the
- * variable err points to.
+ * device pointer returned. %NULL is returned if the name allocation
+ * failed. The cause of an error is returned as a negative errno code
+ * in the variable @err points to.
*
- * The claler must hold the dev_base or rtnl locks when doing this in order
- * to avoid duplicate name allocations.
+ * The caller must hold the @dev_base or RTNL locks when doing this in
+ * order to avoid duplicate name allocations.
*/
struct net_device *dev_alloc(const char *name, int *err)
@@ -520,9 +520,9 @@ static int default_rebuild_header(struct sk_buff *skb)
* dev_open - prepare an interface for use.
* @dev: device to open
*
- * Takes a device from down to up state. The devices private open
+ * Takes a device from down to up state. The device's private open
* function is invoked and then the multicast lists are loaded. Finally
- * the device is moved into the up state and a NETDEV_UP message is
+ * the device is moved into the up state and a %NETDEV_UP message is
* sent to the netdev notifier chain.
*
* Calling this function on an active interface is a nop. On a failure
@@ -622,8 +622,8 @@ void dev_clear_fastroute(struct net_device *dev)
* @dev: device to shutdown
*
* This function moves an active device into down state. A
- * NETDEV_GOING_DOWN is sent to the netev notifier chain. The device
- * is then deactivated and finally a NETDEV_DOWN is sent to the notifier
+ * %NETDEV_GOING_DOWN is sent to the netdev notifier chain. The device
+ * is then deactivated and finally a %NETDEV_DOWN is sent to the notifier
* chain.
*/
@@ -695,9 +695,10 @@ int register_netdevice_notifier(struct notifier_block *nb)
* unregister_netdevice_notifier - unregister a network notifier block
* @nb: notifier
*
- * Unregister a notifier previously registered by register_netdevice_notifier
- * The notifier is unlinked into the kernel structures and may
- * then be reused. A negative errno code is returned on a failure.
+ * Unregister a notifier previously registered by
+ * register_netdevice_notifier(). The notifier is unlinked into the
+ * kernel structures and may then be reused. A negative errno code
+ * is returned on a failure.
*/
int unregister_netdevice_notifier(struct notifier_block *nb)
@@ -1079,7 +1080,7 @@ static void net_tx_action(struct softirq_action *h)
* @fn: function to call
*
* Make a function call that is atomic with respect to the protocol
- * layers
+ * layers.
*/
void net_call_rx_atomic(void (*fn)(void))
@@ -1426,10 +1427,11 @@ static int dev_get_info(char *buffer, char **start, off_t offset, int length)
static int dev_proc_stats(char *buffer, char **start, off_t offset,
int length, int *eof, void *data)
{
- int i;
+ int i, lcpu;
int len=0;
- for (i=0; i<smp_num_cpus; i++) {
+ for (lcpu=0; lcpu<smp_num_cpus; lcpu++) {
+ i = cpu_logical_map(lcpu);
len += sprintf(buffer+len, "%08x %08x %08x %08x %08x %08x %08x %08x %08x\n",
netdev_rx_stat[i].total,
netdev_rx_stat[i].dropped,
@@ -1554,10 +1556,10 @@ static int dev_get_wireless_info(char * buffer, char **start, off_t offset,
* @slave: slave device
* @master: new master device
*
- * Changes the master device of the slave. Pass NULL to break the
+ * Changes the master device of the slave. Pass %NULL to break the
* bonding. The caller must hold the RTNL semaphore. On a failure
* a negative errno code is returned. On success the reference counts
- * are adjusted, RTM_NEWLINK is sent to the routing socket and the
+ * are adjusted, %RTM_NEWLINK is sent to the routing socket and the
* function returns zero.
*/
@@ -1629,7 +1631,7 @@ void dev_set_promiscuity(struct net_device *dev, int inc)
* Add or remove reception of all multicast frames to a device. While the
* count in the device remains above zero the interface remains listening
* to all interfaces. Once it hits zero the device reverts back to normal
- * filtering operation. A negative inc value is used to drop the counter
+ * filtering operation. A negative @inc value is used to drop the counter
* when releasing a resource needing all multicasts.
*/
@@ -2005,12 +2007,16 @@ int dev_ioctl(unsigned int cmd, void *arg)
return ret;
}
#ifdef WIRELESS_EXT
+ /* Take care of Wireless Extensions */
if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
- dev_load(ifr.ifr_name);
- if (IW_IS_SET(cmd)) {
- if (!suser())
+ /* If command is `set a parameter', or
+ * `get the encoding parameters', check if
+ * the user has the right to do it */
+ if (IW_IS_SET(cmd) || (cmd == SIOCGIWENCODE)) {
+ if(!capable(CAP_NET_ADMIN))
return -EPERM;
}
+ dev_load(ifr.ifr_name);
rtnl_lock();
ret = dev_ifsioc(&ifr, cmd);
rtnl_unlock();
@@ -2051,7 +2057,7 @@ static int dev_boot_phase = 1;
* @dev: device to register
*
* Take a completed network device structure and add it to the kernel
- * interfaces. A NETDEV_REGISTER message is sent to the netdev notifier
+ * interfaces. A %NETDEV_REGISTER message is sent to the netdev notifier
* chain. 0 is returned on success. A negative errno code is returned
* on a failure to set up the device, or if the name is a duplicate.
*
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index d97bdc5f2..5a3ccd062 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -54,7 +54,7 @@ static int pneigh_ifdown(struct neigh_table *tbl, struct net_device *dev);
static int neigh_glbl_allocs;
static struct neigh_table *neigh_tables;
-#if defined(__i386__) && defined(__SMP__)
+#if defined(__i386__) && defined(CONFIG_SMP)
#define ASSERT_WL(n) if ((int)((n)->lock.lock) > 0) { printk("WL assertion failed at " __FILE__ "(%d):" __FUNCTION__ "\n", __LINE__); }
#else
#define ASSERT_WL(n) do { } while(0)
@@ -597,7 +597,7 @@ next_elt:
write_unlock(&tbl->lock);
}
-#ifdef __SMP__
+#ifdef CONFIG_SMP
static void neigh_periodic_timer(unsigned long arg)
{
struct neigh_table *tbl = (struct neigh_table*)arg;
@@ -629,7 +629,7 @@ static void neigh_timer_handler(unsigned long arg)
state = neigh->nud_state;
if (!(state&NUD_IN_TIMER)) {
-#ifndef __SMP__
+#ifndef CONFIG_SMP
printk("neigh: timer & !nud_in_timer\n");
#endif
goto out;
@@ -1106,7 +1106,7 @@ void neigh_table_init(struct neigh_table *tbl)
0, SLAB_HWCACHE_ALIGN,
NULL, NULL);
-#ifdef __SMP__
+#ifdef CONFIG_SMP
tasklet_init(&tbl->gc_task, SMP_TIMER_NAME(neigh_periodic_timer), (unsigned long)tbl);
#endif
init_timer(&tbl->gc_timer);
diff --git a/net/core/netfilter.c b/net/core/netfilter.c
index 02c3bc989..7f9b9e82b 100644
--- a/net/core/netfilter.c
+++ b/net/core/netfilter.c
@@ -186,18 +186,10 @@ void nf_dump_skb(int pf, struct sk_buff *skb)
dst_port = ntohs(tcp->dest);
}
- printk("PROTO=%d %d.%d.%d.%d:%hu %d.%d.%d.%d:%hu"
+ printk("PROTO=%d %u.%u.%u.%u:%hu %u.%u.%u.%u:%hu"
" L=%hu S=0x%2.2hX I=%hu F=0x%4.4hX T=%hu",
- ip->protocol,
- (ntohl(ip->saddr)>>24)&0xFF,
- (ntohl(ip->saddr)>>16)&0xFF,
- (ntohl(ip->saddr)>>8)&0xFF,
- (ntohl(ip->saddr))&0xFF,
- src_port,
- (ntohl(ip->daddr)>>24)&0xFF,
- (ntohl(ip->daddr)>>16)&0xFF,
- (ntohl(ip->daddr)>>8)&0xFF,
- (ntohl(ip->daddr))&0xFF,
+ ip->protocol, NIPQUAD(ip->saddr),
+ src_port, NIPQUAD(ip->daddr),
dst_port,
ntohs(ip->tot_len), ip->tos, ntohs(ip->id),
ntohs(ip->frag_off), ip->ttl);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 54230a273..234e9c182 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -4,7 +4,7 @@
* Authors: Alan Cox <iiitac@pyr.swan.ac.uk>
* Florian La Roche <rzsfl@rz.uni-sb.de>
*
- * Version: $Id: skbuff.c,v 1.71 2000/03/29 11:58:33 davem Exp $
+ * Version: $Id: skbuff.c,v 1.72 2000/04/13 00:55:54 davem Exp $
*
* Fixes:
* Alan Cox : Fixed the worst of the load balancer bugs.
@@ -83,7 +83,7 @@ static union {
* @sz: size
* @here: address
*
- * Out of line support code for skb_put. Not user callable
+ * Out of line support code for skb_put(). Not user callable.
*/
void skb_over_panic(struct sk_buff *skb, int sz, void *here)
@@ -99,7 +99,7 @@ void skb_over_panic(struct sk_buff *skb, int sz, void *here)
* @sz: size
* @here: address
*
- * Out of line support code for skb_push. Not user callable
+ * Out of line support code for skb_push(). Not user callable.
*/
@@ -154,12 +154,12 @@ static __inline__ void skb_head_to_pool(struct sk_buff *skb)
* @size: size to allocate
* @gfp_mask: allocation mask
*
- * Allocate a new sk_buff. The returned buffer has no headroom and a
+ * Allocate a new &sk_buff. The returned buffer has no headroom and a
* tail room of size bytes. The object has a reference count of one.
- * The return is the buffer. On a failure the return is NULL.
+ * The return is the buffer. On a failure the return is %NULL.
*
- * Buffers may only be allocated from interrupts using a gfp_mask of
- * GFP_ATOMIC.
+ * Buffers may only be allocated from interrupts using a @gfp_mask of
+ * %GFP_ATOMIC.
*/
struct sk_buff *alloc_skb(unsigned int size,int gfp_mask)
@@ -300,13 +300,13 @@ void __kfree_skb(struct sk_buff *skb)
* @skb: buffer to clone
* @gfp_mask: allocation priority
*
- * Duplicate an sk_buff. The new one is not owned by a socket. Both
+ * Duplicate an &sk_buff. The new one is not owned by a socket. Both
* copies share the same packet data but not structure. The new
* buffer has a reference count of 1. If the allocation fails the
- * function returns NULL otherwise the new buffer is returned.
+ * function returns %NULL otherwise the new buffer is returned.
*
- * If this function is called from an interrupt gfp_mask must be
- * GFP_ATOMIC.
+ * If this function is called from an interrupt gfp_mask() must be
+ * %GFP_ATOMIC.
*/
struct sk_buff *skb_clone(struct sk_buff *skb, int gfp_mask)
@@ -383,12 +383,12 @@ static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
* @skb: buffer to copy
* @gfp_mask: allocation priority
*
- * Make a copy of both an sk_buff and its data. This is used when the
+ * Make a copy of both an &sk_buff and its data. This is used when the
* caller wishes to modify the data and needs a private copy of the
- * data to alter. Returns NULL on failure or the pointer to the buffer
+ * data to alter. Returns %NULL on failure or the pointer to the buffer
* on success. The returned buffer has a reference count of 1.
*
- * You must pass GFP_ATOMIC as the allocation priority if this function
+ * You must pass %GFP_ATOMIC as the allocation priority if this function
* is called from an interrupt.
*/
@@ -423,15 +423,15 @@ struct sk_buff *skb_copy(const struct sk_buff *skb, int gfp_mask)
* @newtailroom: new free bytes at tail
* @gfp_mask: allocation priority
*
- * Make a copy of both an sk_buff and its data and while doing so
+ * Make a copy of both an &sk_buff and its data and while doing so
* allocate additional space.
*
* This is used when the caller wishes to modify the data and needs a
* private copy of the data to alter as well as more space for new fields.
- * Returns NULL on failure or the pointer to the buffer
+ * Returns %NULL on failure or the pointer to the buffer
* on success. The returned buffer has a reference count of 1.
*
- * You must pass GFP_ATOMIC as the allocation priority if this function
+ * You must pass %GFP_ATOMIC as the allocation priority if this function
* is called from an interrupt.
*/
diff --git a/net/core/sock.c b/net/core/sock.c
index ce25381c9..4044a7f7d 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -7,7 +7,7 @@
* handler for protocols to use and generic option handler.
*
*
- * Version: $Id: sock.c,v 1.91 2000/03/25 01:55:03 davem Exp $
+ * Version: $Id: sock.c,v 1.93 2000/04/13 03:13:29 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -786,18 +786,22 @@ struct sk_buff *sock_alloc_send_skb(struct sock *sk, unsigned long size,
if (sk->shutdown&SEND_SHUTDOWN)
goto failure;
- if (fallback) {
- /* The buffer get won't block, or use the atomic queue.
- * It does produce annoying no free page messages still.
- */
- skb = sock_wmalloc(sk, size, 0, GFP_BUFFER);
+ if (atomic_read(&sk->wmem_alloc) < sk->sndbuf) {
+ if (fallback) {
+ /* The buffer get won't block, or use the atomic queue.
+ * It does produce annoying no free page messages still.
+ */
+ skb = alloc_skb(size, GFP_BUFFER);
+ if (skb)
+ break;
+ try_size = fallback;
+ }
+ skb = alloc_skb(try_size, sk->allocation);
if (skb)
break;
- try_size = fallback;
+ err = -ENOBUFS;
+ goto failure;
}
- skb = sock_wmalloc(sk, try_size, 0, sk->allocation);
- if (skb)
- break;
/*
* This means we have too many buffers for this socket already.
@@ -813,6 +817,7 @@ struct sk_buff *sock_alloc_send_skb(struct sock *sk, unsigned long size,
timeo = sock_wait_for_wmem(sk, timeo);
}
+ skb_set_owner_w(skb, sk);
return skb;
interrupted:
@@ -1063,7 +1068,7 @@ int sock_no_sendmsg(struct socket *sock, struct msghdr *m, int flags,
return -EOPNOTSUPP;
}
-int sock_no_recvmsg(struct socket *sock, struct msghdr *m, int flags,
+int sock_no_recvmsg(struct socket *sock, struct msghdr *m, int len, int flags,
struct scm_cookie *scm)
{
return -EOPNOTSUPP;
@@ -1136,7 +1141,6 @@ void sock_init_data(struct socket *sock, struct sock *sk)
skb_queue_head_init(&sk->write_queue);
skb_queue_head_init(&sk->error_queue);
- spin_lock_init(&sk->timer_lock);
init_timer(&sk->timer);
sk->allocation = GFP_KERNEL;
diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c
index c560ea01e..ab244350e 100644
--- a/net/decnet/af_decnet.c
+++ b/net/decnet/af_decnet.c
@@ -2032,24 +2032,23 @@ static struct net_proto_family dn_family_ops = {
};
static struct proto_ops dn_proto_ops = {
- AF_DECnet,
-
- dn_release,
- dn_bind,
- dn_connect,
- sock_no_socketpair,
- dn_accept,
- dn_getname,
- dn_poll,
- dn_ioctl,
- dn_listen,
- dn_shutdown,
- dn_setsockopt,
- dn_getsockopt,
- sock_no_fcntl,
- dn_sendmsg,
- dn_recvmsg,
- sock_no_mmap
+ family: AF_DECnet,
+
+ release: dn_release,
+ bind: dn_bind,
+ connect: dn_connect,
+ socketpair: sock_no_socketpair,
+ accept: dn_accept,
+ getname: dn_getname,
+ poll: dn_poll,
+ ioctl: dn_ioctl,
+ listen: dn_listen,
+ shutdown: dn_shutdown,
+ setsockopt: dn_setsockopt,
+ getsockopt: dn_getsockopt,
+ sendmsg: dn_sendmsg,
+ recvmsg: dn_recvmsg,
+ mmap: sock_no_mmap,
};
#ifdef CONFIG_SYSCTL
@@ -2091,7 +2090,7 @@ static int __init decnet_setup(char *str)
decnet_address = dn_htons(area << 10 | node);
dn_dn2eth(decnet_ether_address, dn_ntohs(decnet_address));
- return 0;
+ return 1;
}
__setup("decnet=", decnet_setup);
diff --git a/net/decnet/sysctl_net_decnet.c b/net/decnet/sysctl_net_decnet.c
index ff65e9ae6..c1931c867 100644
--- a/net/decnet/sysctl_net_decnet.c
+++ b/net/decnet/sysctl_net_decnet.c
@@ -54,6 +54,22 @@ static struct ctl_table_header *dn_table_header = NULL;
#define ISALPHA(x) (ISLOWER(x) || ISUPPER(x))
#define INVALID_END_CHAR(x) (ISNUM(x) || ISALPHA(x))
+static void strip_it(char *str)
+{
+ for(;;) {
+ switch(*str) {
+ case ' ':
+ case '\n':
+ case '\r':
+ case ':':
+ *str = 0;
+ case 0:
+ return;
+ }
+ str++;
+ }
+}
+
/*
* Simple routine to parse an ascii DECnet address
* into a network order address.
@@ -159,8 +175,9 @@ static int dn_node_address_handler(ctl_table *table, int write,
return -EFAULT;
addr[len] = 0;
+ strip_it(addr);
- if (parse_addr(&dnaddr, buffer))
+ if (parse_addr(&dnaddr, addr))
return -EINVAL;
dn_dev_devices_off();
@@ -257,8 +274,6 @@ static int dn_def_dev_handler(ctl_table *table, int write,
}
if (write) {
- int i;
-
if (*lenp > 16)
return -E2BIG;
@@ -266,9 +281,7 @@ static int dn_def_dev_handler(ctl_table *table, int write,
return -EFAULT;
devname[*lenp] = 0;
- for(i = 0; i < (*lenp); i++)
- if (devname[i] == '\n')
- devname[i] = 0;
+ strip_it(devname);
if ((dev = __dev_get_by_name(devname)) == NULL)
return -ENODEV;
diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c
index a22098207..79ae4d3ca 100644
--- a/net/econet/af_econet.c
+++ b/net/econet/af_econet.c
@@ -705,24 +705,23 @@ static struct net_proto_family econet_family_ops = {
};
static struct proto_ops SOCKOPS_WRAPPED(econet_ops) = {
- PF_ECONET,
-
- econet_release,
- econet_bind,
- sock_no_connect,
- sock_no_socketpair,
- sock_no_accept,
- econet_getname,
- datagram_poll,
- econet_ioctl,
- sock_no_listen,
- sock_no_shutdown,
- sock_no_setsockopt,
- sock_no_getsockopt,
- sock_no_fcntl,
- econet_sendmsg,
- econet_recvmsg,
- sock_no_mmap
+ family: PF_ECONET,
+
+ release: econet_release,
+ bind: econet_bind,
+ connect: sock_no_connect,
+ socketpair: sock_no_socketpair,
+ accept: sock_no_accept,
+ getname: econet_getname,
+ poll: datagram_poll,
+ ioctl: econet_ioctl,
+ listen: sock_no_listen,
+ shutdown: sock_no_shutdown,
+ setsockopt: sock_no_setsockopt,
+ getsockopt: sock_no_getsockopt,
+ sendmsg: econet_sendmsg,
+ recvmsg: econet_recvmsg,
+ mmap: sock_no_mmap,
};
#include <linux/smp_lock.h>
@@ -1131,7 +1130,7 @@ void __exit econet_proto_exit(void)
#endif
}
-int __init econet_proto_init(struct net_proto *pro)
+int __init econet_proto_init(void)
{
extern void econet_sysctl_register(void);
sock_register(&econet_family_ops);
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index d3fc0e38f..40aa7cd3a 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -5,7 +5,7 @@
*
* PF_INET protocol family socket handler.
*
- * Version: $Id: af_inet.c,v 1.109 2000/03/25 01:55:10 davem Exp $
+ * Version: $Id: af_inet.c,v 1.110 2000/04/25 04:13:34 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -893,45 +893,43 @@ static int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
}
struct proto_ops inet_stream_ops = {
- PF_INET,
-
- inet_release,
- inet_bind,
- inet_stream_connect,
- sock_no_socketpair,
- inet_accept,
- inet_getname,
- tcp_poll,
- inet_ioctl,
- inet_listen,
- inet_shutdown,
- inet_setsockopt,
- inet_getsockopt,
- sock_no_fcntl,
- inet_sendmsg,
- inet_recvmsg,
- sock_no_mmap
+ family: PF_INET,
+
+ release: inet_release,
+ bind: inet_bind,
+ connect: inet_stream_connect,
+ socketpair: sock_no_socketpair,
+ accept: inet_accept,
+ getname: inet_getname,
+ poll: tcp_poll,
+ ioctl: inet_ioctl,
+ listen: inet_listen,
+ shutdown: inet_shutdown,
+ setsockopt: inet_setsockopt,
+ getsockopt: inet_getsockopt,
+ sendmsg: inet_sendmsg,
+ recvmsg: inet_recvmsg,
+ mmap: sock_no_mmap
};
struct proto_ops inet_dgram_ops = {
- PF_INET,
-
- inet_release,
- inet_bind,
- inet_dgram_connect,
- sock_no_socketpair,
- sock_no_accept,
- inet_getname,
- datagram_poll,
- inet_ioctl,
- sock_no_listen,
- inet_shutdown,
- inet_setsockopt,
- inet_getsockopt,
- sock_no_fcntl,
- inet_sendmsg,
- inet_recvmsg,
- sock_no_mmap
+ family: PF_INET,
+
+ release: inet_release,
+ bind: inet_bind,
+ connect: inet_dgram_connect,
+ socketpair: sock_no_socketpair,
+ accept: sock_no_accept,
+ getname: inet_getname,
+ poll: datagram_poll,
+ ioctl: inet_ioctl,
+ listen: sock_no_listen,
+ shutdown: inet_shutdown,
+ setsockopt: inet_setsockopt,
+ getsockopt: inet_getsockopt,
+ sendmsg: inet_sendmsg,
+ recvmsg: inet_recvmsg,
+ mmap: sock_no_mmap,
};
struct net_proto_family inet_family_ops = {
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index 588cdf030..9def6b16b 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -1,6 +1,6 @@
/* linux/net/inet/arp.c
*
- * Version: $Id: arp.c,v 1.84 2000/01/18 08:24:14 davem Exp $
+ * Version: $Id: arp.c,v 1.86 2000/04/26 09:36:36 davem Exp $
*
* Copyright (C) 1994 by Florian La Roche
*
@@ -1021,7 +1021,6 @@ static int arp_get_info(char *buffer, char **start, off_t offset, int length)
char hbuffer[HBUFFERLEN];
int i,j,k;
const char hexbuf[] = "0123456789ABCDEF";
- char abuf[16];
size = sprintf(buffer,"IP address HW type Flags HW address Mask Device\n");
@@ -1060,15 +1059,21 @@ static int arp_get_info(char *buffer, char **start, off_t offset, int length)
}
#endif
- size = sprintf(buffer+len,
- "%-17s0x%-10x0x%-10x%s",
- in_ntoa2(*(u32*)n->primary_key, abuf),
- hatype,
- arp_state_to_flags(n),
- hbuffer);
- size += sprintf(buffer+len+size,
- " %-17s %s\n",
- "*", dev->name);
+ {
+ char tbuf[16];
+ sprintf(tbuf, "%u.%u.%u.%u", NIPQUAD(*(u32*)n->primary_key));
+
+ size = sprintf(buffer+len, "%-16s 0x%-10x0x%-10x%s",
+ tbuf,
+ hatype,
+ arp_state_to_flags(n),
+ hbuffer);
+
+ size += sprintf(buffer+len+size,
+ " %-8s %s\n",
+ "*", dev->name);
+ }
+
read_unlock(&n->lock);
len += size;
@@ -1091,8 +1096,8 @@ static int arp_get_info(char *buffer, char **start, off_t offset, int length)
int hatype = dev ? dev->type : 0;
size = sprintf(buffer+len,
- "%-17s0x%-10x0x%-10x%s",
- in_ntoa2(*(u32*)n->key, abuf),
+ "%u.%u.%u.%u0x%-10x0x%-10x%s",
+ NIPQUAD(*(u32*)n->key),
hatype,
ATF_PUBL|ATF_PERM,
"00:00:00:00:00:00");
diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c
index 5ee1bfd78..03095f1a2 100644
--- a/net/ipv4/fib_rules.c
+++ b/net/ipv4/fib_rules.c
@@ -5,7 +5,7 @@
*
* IPv4 Forwarding Information Base: policy rules.
*
- * Version: $Id: fib_rules.c,v 1.14 1999/08/31 07:03:29 davem Exp $
+ * Version: $Id: fib_rules.c,v 1.15 2000/04/15 01:48:10 davem Exp $
*
* Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
*
@@ -298,7 +298,8 @@ int fib_lookup(const struct rt_key *key, struct fib_result *res)
u32 daddr = key->dst;
u32 saddr = key->src;
-FRprintk("Lookup: %08x <- %08x ", key->dst, key->src);
+FRprintk("Lookup: %u.%u.%u.%u <- %u.%u.%u.%u ",
+ NIPQUAD(key->dst), NIPQUAD(key->src));
read_lock(&fib_rules_lock);
for (r = fib_rules; r; r=r->r_next) {
if (((saddr^r->r_src) & r->r_srcmask) ||
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index 7c462ac08..f15d94388 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -3,7 +3,7 @@
*
* Alan Cox, <alan@redhat.com>
*
- * Version: $Id: icmp.c,v 1.67 2000/03/25 01:55:11 davem Exp $
+ * Version: $Id: icmp.c,v 1.69 2000/04/15 01:48:10 davem Exp $
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -521,9 +521,12 @@ void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)
}
if (ip_route_output(&rt, daddr, rt->rt_spec_dst, RT_TOS(skb->nh.iph->tos), 0))
goto out;
- ip_build_xmit(sk, icmp_glue_bits, icmp_param,
- icmp_param->data_len+sizeof(struct icmphdr),
- &ipc, rt, MSG_DONTWAIT);
+ if (icmpv4_xrlim_allow(rt, icmp_param->icmph.type,
+ icmp_param->icmph.code)) {
+ ip_build_xmit(sk, icmp_glue_bits, icmp_param,
+ icmp_param->data_len+sizeof(struct icmphdr),
+ &ipc, rt, MSG_DONTWAIT);
+ }
ip_rt_put(rt);
out:
icmp_xmit_unlock_bh();
@@ -720,7 +723,7 @@ static void icmp_unreach(struct icmphdr *icmph, struct sk_buff *skb, int len)
case ICMP_FRAG_NEEDED:
if (ipv4_config.no_pmtu_disc) {
if (net_ratelimit())
- printk(KERN_INFO "ICMP: %d.%d.%d.%d: fragmentation needed and DF set.\n",
+ printk(KERN_INFO "ICMP: %u.%u.%u.%u: fragmentation needed and DF set.\n",
NIPQUAD(iph->daddr));
} else {
unsigned short new_mtu;
@@ -732,7 +735,7 @@ static void icmp_unreach(struct icmphdr *icmph, struct sk_buff *skb, int len)
break;
case ICMP_SR_FAILED:
if (net_ratelimit())
- printk(KERN_INFO "ICMP: %d.%d.%d.%d: Source Route Failed.\n", NIPQUAD(iph->daddr));
+ printk(KERN_INFO "ICMP: %u.%u.%u.%u: Source Route Failed.\n", NIPQUAD(iph->daddr));
break;
default:
break;
@@ -762,7 +765,7 @@ static void icmp_unreach(struct icmphdr *icmph, struct sk_buff *skb, int len)
if (inet_addr_type(iph->daddr) == RTN_BROADCAST)
{
if (net_ratelimit())
- printk(KERN_WARNING "%d.%d.%d.%d sent an invalid ICMP error to a broadcast.\n",
+ printk(KERN_WARNING "%u.%u.%u.%u sent an invalid ICMP error to a broadcast.\n",
NIPQUAD(skb->nh.iph->saddr));
return;
}
@@ -983,9 +986,8 @@ static void icmp_address_reply(struct icmphdr *icmph, struct sk_buff *skb, int l
break;
}
if (!ifa && net_ratelimit()) {
- char b1[16], b2[16];
- printk(KERN_INFO "Wrong address mask %s from %s/%s\n",
- in_ntoa2(mask, b1), in_ntoa2(rt->rt_src, b2), dev->name);
+ printk(KERN_INFO "Wrong address mask %u.%u.%u.%u from %s/%u.%u.%u.%u\n",
+ NIPQUAD(mask), dev->name, NIPQUAD(rt->rt_src));
}
}
read_unlock(&in_dev->lock);
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index 852a4fb2c..70f8cfb90 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -5,7 +5,7 @@
*
* The IP fragmentation functionality.
*
- * Version: $Id: ip_fragment.c,v 1.47 2000/02/09 21:11:33 davem Exp $
+ * Version: $Id: ip_fragment.c,v 1.49 2000/04/15 01:48:10 davem Exp $
*
* Authors: Fred N. van Kempen <waltje@uWalt.NL.Mugnet.ORG>
* Alan Cox <Alan.Cox@linux.org>
@@ -387,9 +387,14 @@ static struct sk_buff *ip_glue(struct ipq *qp)
*/
skb->security = qp->fragments->skb->security;
+#ifdef CONFIG_NETFILTER
+ /* Connection association is same as fragment (if any). */
+ skb->nfct = qp->fragments->skb->nfct;
+ nf_conntrack_get(skb->nfct);
#ifdef CONFIG_NETFILTER_DEBUG
skb->nf_debug = qp->fragments->skb->nf_debug;
#endif
+#endif
/* Done with all fragments. Fixup the new IP header. */
iph = skb->nh.iph;
@@ -594,7 +599,7 @@ out:
*/
out_oversize:
if (net_ratelimit())
- printk(KERN_INFO "Oversized packet received from %d.%d.%d.%d\n",
+ printk(KERN_INFO "Oversized packet received from %u.%u.%u.%u\n",
NIPQUAD(iph->saddr));
/* the skb isn't in a fragment, so fall through to free it */
out_freeskb:
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
index 0c755dbcd..700bb24f7 100644
--- a/net/ipv4/ip_input.c
+++ b/net/ipv4/ip_input.c
@@ -5,7 +5,7 @@
*
* The Internet Protocol (IP) module.
*
- * Version: $Id: ip_input.c,v 1.46 2000/02/22 23:54:26 davem Exp $
+ * Version: $Id: ip_input.c,v 1.48 2000/04/15 01:48:10 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -162,7 +162,13 @@ int ip_call_ra_chain(struct sk_buff *skb)
read_lock(&ip_ra_lock);
for (ra = ip_ra_chain; ra; ra = ra->next) {
struct sock *sk = ra->sk;
- if (sk && sk->num == protocol) {
+
+ /* If socket is bound to an interface, only report
+ * the packet if it came from that interface.
+ */
+ if (sk && sk->num == protocol
+ && ((sk->bound_dev_if == 0)
+ || (sk->bound_dev_if == skb->dev->ifindex))) {
if (skb->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
skb = ip_defrag(skb);
if (skb == NULL) {
@@ -349,7 +355,7 @@ static inline int ip_rcv_finish(struct sk_buff *skb)
if (in_dev) {
if (!IN_DEV_SOURCE_ROUTE(in_dev)) {
if (IN_DEV_LOG_MARTIANS(in_dev) && net_ratelimit())
- printk(KERN_INFO "source route option %d.%d.%d.%d -> %d.%d.%d.%d\n",
+ printk(KERN_INFO "source route option %u.%u.%u.%u -> %u.%u.%u.%u\n",
NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
in_dev_put(in_dev);
goto drop;
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c
index 454e81fea..cd51bcef3 100644
--- a/net/ipv4/ipconfig.c
+++ b/net/ipv4/ipconfig.c
@@ -1,5 +1,5 @@
/*
- * $Id: ipconfig.c,v 1.27 2000/02/21 15:51:41 davem Exp $
+ * $Id: ipconfig.c,v 1.30 2000/04/15 01:48:10 davem Exp $
*
* Automatic Configuration of IP -- use BOOTP or RARP or user-supplied
* information to configure own IP address and routes.
@@ -77,7 +77,7 @@ u8 root_server_path[256] __initdata = { 0, }; /* Path to mount as root */
#define CONFIG_IP_PNP_DYNAMIC
-static int ic_proto_enabled __initdata = 0 /* Protocols enabled */
+int ic_proto_enabled __initdata = 0 /* Protocols enabled */
#ifdef CONFIG_IP_PNP_BOOTP
| IC_BOOTP
#endif
@@ -227,17 +227,20 @@ static int __init ic_setup_if(void)
strcpy(ir.ifr_ifrn.ifrn_name, ic_dev->name);
set_sockaddr(sin, ic_myaddr, 0);
if ((err = ic_dev_ioctl(SIOCSIFADDR, &ir)) < 0) {
- printk(KERN_ERR "IP-Config: Unable to set interface address (%d).\n", err);
+ printk(KERN_ERR "IP-Config: Unable to set interface address (%u.%u.%u.%u).\n",
+ NIPQUAD(err));
return -1;
}
set_sockaddr(sin, ic_netmask, 0);
if ((err = ic_dev_ioctl(SIOCSIFNETMASK, &ir)) < 0) {
- printk(KERN_ERR "IP-Config: Unable to set interface netmask (%d).\n", err);
+ printk(KERN_ERR "IP-Config: Unable to set interface netmask (%u.%u.%u.%u).\n",
+ NIPQUAD(err));
return -1;
}
set_sockaddr(sin, ic_myaddr | ~ic_netmask, 0);
if ((err = ic_dev_ioctl(SIOCSIFBRDADDR, &ir)) < 0) {
- printk(KERN_ERR "IP-Config: Unable to set interface broadcast address (%d).\n", err);
+ printk(KERN_ERR "IP-Config: Unable to set interface broadcast address (%u.%u.%u.%u).\n",
+ NIPQUAD(err));
return -1;
}
return 0;
@@ -261,7 +264,8 @@ static int __init ic_setup_routes(void)
set_sockaddr((struct sockaddr_in *) &rm.rt_gateway, ic_gateway, 0);
rm.rt_flags = RTF_UP | RTF_GATEWAY;
if ((err = ic_route_ioctl(SIOCADDRT, &rm)) < 0) {
- printk(KERN_ERR "IP-Config: Cannot add default route (%d).\n", err);
+ printk(KERN_ERR "IP-Config: Cannot add default route (%u.%u.%u.%u).\n",
+ NIPQUAD(err));
return -1;
}
}
@@ -294,10 +298,11 @@ static int __init ic_defaults(void)
else if (IN_CLASSC(ntohl(ic_myaddr)))
ic_netmask = htonl(IN_CLASSC_NET);
else {
- printk(KERN_ERR "IP-Config: Unable to guess netmask for address %08x\n", ic_myaddr);
+ printk(KERN_ERR "IP-Config: Unable to guess netmask for address %u.%u.%u.%u\n",
+ NIPQUAD(ic_myaddr));
return -1;
}
- printk("IP-Config: Guessing netmask %s\n", in_ntoa(ic_netmask));
+ printk("IP-Config: Guessing netmask %u.%u.%u.%u\n", NIPQUAD(ic_netmask));
}
return 0;
@@ -807,10 +812,10 @@ static int __init ic_dynamic(void)
if (!ic_got_reply)
return -1;
- printk("IP-Config: Got %s answer from %s, ",
+ printk("IP-Config: Got %s answer from %u.%u.%u.%u, ",
(ic_got_reply & IC_BOOTP) ? "BOOTP" : "RARP",
- in_ntoa(ic_servaddr));
- printk("my address is %s\n", in_ntoa(ic_myaddr));
+ NIPQUAD(ic_servaddr));
+ printk("my address is %u.%u.%u.%u\n", NIPQUAD(ic_myaddr));
return 0;
}
@@ -986,7 +991,7 @@ static int __init ip_auto_config_setup(char *addrs)
num++;
}
- return 0;
+ return 1;
}
static int __init nfsaddrs_config_setup(char *addrs)
diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c
index 197c2e3b4..fdfd747e2 100644
--- a/net/ipv4/netfilter/ip_conntrack_core.c
+++ b/net/ipv4/netfilter/ip_conntrack_core.c
@@ -343,6 +343,7 @@ init_conntrack(const struct ip_conntrack_tuple *tuple,
size_t hash, repl_hash;
struct ip_conntrack_expect *expected;
enum ip_conntrack_info ctinfo;
+ unsigned long extra_jiffies;
int i;
if (!invert_tuple(&repl_tuple, tuple, protocol)) {
@@ -366,19 +367,24 @@ init_conntrack(const struct ip_conntrack_tuple *tuple,
repl_hash = hash_conntrack(&repl_tuple);
memset(conntrack, 0, sizeof(struct ip_conntrack));
- atomic_set(&conntrack->ct_general.use, 1);
+ atomic_set(&conntrack->ct_general.use, 2);
conntrack->ct_general.destroy = destroy_conntrack;
conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple = *tuple;
conntrack->tuplehash[IP_CT_DIR_ORIGINAL].ctrack = conntrack;
conntrack->tuplehash[IP_CT_DIR_REPLY].tuple = repl_tuple;
conntrack->tuplehash[IP_CT_DIR_REPLY].ctrack = conntrack;
- for(i=0; i < IP_CT_NUMBER; i++)
+ for (i=0; i < IP_CT_NUMBER; i++)
conntrack->infos[i].master = &conntrack->ct_general;
- if (!protocol->new(conntrack, skb->nh.iph, skb->len)) {
+ extra_jiffies = protocol->new(conntrack, skb->nh.iph, skb->len);
+ if (!extra_jiffies) {
kmem_cache_free(ip_conntrack_cachep, conntrack);
return 1;
}
+ conntrack->timeout.data = (unsigned long)conntrack;
+ conntrack->timeout.function = death_by_timeout;
+ conntrack->timeout.expires = jiffies + extra_jiffies;
+ add_timer(&conntrack->timeout);
/* Sew in at head of hash list. */
WRITE_LOCK(&ip_conntrack_lock);
@@ -421,7 +427,7 @@ init_conntrack(const struct ip_conntrack_tuple *tuple,
}
static void
-resolve_normal_ct(struct sk_buff *skb)
+resolve_normal_ct(struct sk_buff *skb, int create)
{
struct ip_conntrack_tuple tuple;
struct ip_conntrack_tuple_hash *h;
@@ -436,7 +442,7 @@ resolve_normal_ct(struct sk_buff *skb)
do {
/* look for tuple match */
h = ip_conntrack_find_get(&tuple, NULL);
- if (!h && init_conntrack(&tuple, proto, skb))
+ if (!h && (!create || init_conntrack(&tuple, proto, skb)))
return;
} while (!h);
@@ -464,13 +470,15 @@ resolve_normal_ct(struct sk_buff *skb)
}
/* Return conntrack and conntrack_info a given skb */
-struct ip_conntrack *
-ip_conntrack_get(struct sk_buff *skb, enum ip_conntrack_info *ctinfo)
+static struct ip_conntrack *
+__ip_conntrack_get(struct sk_buff *skb,
+ enum ip_conntrack_info *ctinfo,
+ int create)
{
if (!skb->nfct) {
/* It may be an icmp error... */
if (!icmp_error_track(skb))
- resolve_normal_ct(skb);
+ resolve_normal_ct(skb, create);
}
if (skb->nfct) {
@@ -485,6 +493,12 @@ ip_conntrack_get(struct sk_buff *skb, enum ip_conntrack_info *ctinfo)
return NULL;
}
+struct ip_conntrack *
+ip_conntrack_get(struct sk_buff *skb, enum ip_conntrack_info *ctinfo)
+{
+ return __ip_conntrack_get(skb, ctinfo, 0);
+}
+
/* Netfilter hook itself. */
unsigned int ip_conntrack_in(unsigned int hooknum,
struct sk_buff **pskb,
@@ -512,13 +526,13 @@ unsigned int ip_conntrack_in(unsigned int hooknum,
return NF_STOLEN;
}
- ct = ip_conntrack_get(*pskb, &ctinfo);
- if (!ct)
+ ct = __ip_conntrack_get(*pskb, &ctinfo, 1);
+ if (!ct) {
/* Not valid part of a connection */
return NF_ACCEPT;
+ }
proto = find_proto((*pskb)->nh.iph->protocol);
- /* If this is new, this is first time timer will be set */
ret = proto->packet(ct, (*pskb)->nh.iph, (*pskb)->len, ctinfo);
if (ret == -1) {
@@ -645,24 +659,16 @@ void ip_conntrack_helper_unregister(struct ip_conntrack_helper *me)
MOD_DEC_USE_COUNT;
}
-/* Refresh conntrack for this many jiffies: if noone calls this,
- conntrack will vanish with current skb. */
+/* Refresh conntrack for this many jiffies. */
void ip_ct_refresh(struct ip_conntrack *ct, unsigned long extra_jiffies)
{
+ IP_NF_ASSERT(ct->timeout.data == (unsigned long)ct);
+
WRITE_LOCK(&ip_conntrack_lock);
- /* If this hasn't had a timer before, it's still being set up */
- if (ct->timeout.data == 0) {
- ct->timeout.data = (unsigned long)ct;
- ct->timeout.function = death_by_timeout;
+ /* Need del_timer for race avoidance (may already be dying). */
+ if (del_timer(&ct->timeout)) {
ct->timeout.expires = jiffies + extra_jiffies;
- atomic_inc(&ct->ct_general.use);
add_timer(&ct->timeout);
- } else {
- /* Need del_timer for race avoidance (may already be dying). */
- if (del_timer(&ct->timeout)) {
- ct->timeout.expires = jiffies + extra_jiffies;
- add_timer(&ct->timeout);
- }
}
WRITE_UNLOCK(&ip_conntrack_lock);
}
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_generic.c b/net/ipv4/netfilter/ip_conntrack_proto_generic.c
index 77a491e34..6e2bcbcec 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_generic.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_generic.c
@@ -48,9 +48,10 @@ static int established(struct ip_conntrack *conntrack,
}
/* Called when a new connection for this protocol found. */
-static int new(struct ip_conntrack *conntrack, struct iphdr *iph, size_t len)
+static unsigned long
+new(struct ip_conntrack *conntrack, struct iphdr *iph, size_t len)
{
- return 1;
+ return GENERIC_TIMEOUT;
}
struct ip_conntrack_protocol ip_conntrack_generic_protocol
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
index cbbc1ab8c..17e126119 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
@@ -86,8 +86,8 @@ static int icmp_packet(struct ip_conntrack *ct,
}
/* Called when a new connection for this protocol found. */
-static int icmp_new(struct ip_conntrack *conntrack,
- struct iphdr *iph, size_t len)
+static unsigned long icmp_new(struct ip_conntrack *conntrack,
+ struct iphdr *iph, size_t len)
{
static u_int8_t valid_new[]
= { [ICMP_ECHO] = 1,
@@ -103,7 +103,7 @@ static int icmp_new(struct ip_conntrack *conntrack,
DUMP_TUPLE(&conntrack->tuplehash[0].tuple);
return 0;
}
- return 1;
+ return ICMP_TIMEOUT;
}
struct ip_conntrack_protocol ip_conntrack_protocol_icmp
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
index 893248943..997a917bc 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
@@ -189,14 +189,13 @@ static int tcp_packet(struct ip_conntrack *conntrack,
conntrack->proto.tcp_state = newconntrack;
WRITE_UNLOCK(&tcp_lock);
- /* Refresh: need write lock to write to conntrack. */
ip_ct_refresh(conntrack, tcp_timeouts[conntrack->proto.tcp_state]);
return NF_ACCEPT;
}
/* Called when a new connection for this protocol found. */
-static int tcp_new(struct ip_conntrack *conntrack,
- struct iphdr *iph, size_t len)
+static unsigned long tcp_new(struct ip_conntrack *conntrack,
+ struct iphdr *iph, size_t len)
{
enum tcp_conntrack newconntrack;
struct tcphdr *tcph = (struct tcphdr *)((u_int32_t *)iph + iph->ihl);
@@ -210,11 +209,10 @@ static int tcp_new(struct ip_conntrack *conntrack,
if (newconntrack == TCP_CONNTRACK_MAX) {
DEBUGP("ip_conntrack_tcp: invalid new deleting.\n");
return 0;
- } else {
- conntrack->proto.tcp_state = newconntrack;
- ip_ct_refresh(conntrack, tcp_timeouts[conntrack->proto.tcp_state]);
}
- return 1;
+
+ conntrack->proto.tcp_state = newconntrack;
+ return tcp_timeouts[conntrack->proto.tcp_state];
}
struct ip_conntrack_protocol ip_conntrack_protocol_tcp
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_udp.c b/net/ipv4/netfilter/ip_conntrack_proto_udp.c
index 79ec82151..521bd7654 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_udp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_udp.c
@@ -54,10 +54,10 @@ static int udp_packet(struct ip_conntrack *conntrack,
}
/* Called when a new connection for this protocol found. */
-static int udp_new(struct ip_conntrack *conntrack,
- struct iphdr *iph, size_t len)
+static unsigned long udp_new(struct ip_conntrack *conntrack,
+ struct iphdr *iph, size_t len)
{
- return 1;
+ return UDP_TIMEOUT;
}
struct ip_conntrack_protocol ip_conntrack_protocol_udp
diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c
index 9030d9d41..3219f4c85 100644
--- a/net/ipv4/netfilter/ip_conntrack_standalone.c
+++ b/net/ipv4/netfilter/ip_conntrack_standalone.c
@@ -169,8 +169,6 @@ static unsigned int ip_refrag(unsigned int hooknum,
interface. We degfragment them at LOCAL_OUT, however,
so we have to refragment them here. */
if ((*pskb)->len > rt->u.dst.pmtu) {
- DEBUGP("ip_conntrack: refragm %p (size %u) to %u (okfn %p)\n",
- *pskb, (*pskb)->len, rt->u.dst.pmtu, okfn);
/* No hook can be after us, so this should be OK. */
ip_fragment(*pskb, okfn);
return NF_STOLEN;
@@ -178,13 +176,29 @@ static unsigned int ip_refrag(unsigned int hooknum,
return NF_ACCEPT;
}
+static unsigned int ip_conntrack_local(unsigned int hooknum,
+ struct sk_buff **pskb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
+{
+ /* root is playing with raw sockets. */
+ if ((*pskb)->len < sizeof(struct iphdr)
+ || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr)) {
+ if (net_ratelimit())
+ printk("ipt_hook: happy cracking.\n");
+ return NF_ACCEPT;
+ }
+ return ip_conntrack_in(hooknum, pskb, in, out, okfn);
+}
+
/* Connection tracking may drop packets, but never alters them, so
make it the first hook. */
static struct nf_hook_ops ip_conntrack_in_ops
= { { NULL, NULL }, ip_conntrack_in, PF_INET, NF_IP_PRE_ROUTING,
NF_IP_PRI_CONNTRACK };
static struct nf_hook_ops ip_conntrack_local_out_ops
-= { { NULL, NULL }, ip_conntrack_in, PF_INET, NF_IP_LOCAL_OUT,
+= { { NULL, NULL }, ip_conntrack_local, PF_INET, NF_IP_LOCAL_OUT,
NF_IP_PRI_CONNTRACK };
/* Refragmenter; last chance. */
static struct nf_hook_ops ip_conntrack_out_ops
diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c
index bfcc435c2..0c582b867 100644
--- a/net/ipv4/netfilter/ip_nat_standalone.c
+++ b/net/ipv4/netfilter/ip_nat_standalone.c
@@ -130,6 +130,11 @@ ip_nat_out(unsigned int hooknum,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
+ /* root is playing with raw sockets. */
+ if ((*pskb)->len < sizeof(struct iphdr)
+ || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
+ return NF_ACCEPT;
+
/* We can hit fragment here; forwarded packets get
defragmented by connection tracking coming in, then
fragmented (grr) by the forward code.
@@ -150,6 +155,21 @@ ip_nat_out(unsigned int hooknum,
return ip_nat_fn(hooknum, pskb, in, out, okfn);
}
+static unsigned int
+ip_nat_local_fn(unsigned int hooknum,
+ struct sk_buff **pskb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
+{
+ /* root is playing with raw sockets. */
+ if ((*pskb)->len < sizeof(struct iphdr)
+ || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
+ return NF_ACCEPT;
+
+ return ip_nat_fn(hooknum, pskb, in, out, okfn);
+}
+
/* We must be after connection tracking and before packet filtering. */
/* Before packet filtering, change destination */
@@ -160,7 +180,7 @@ static struct nf_hook_ops ip_nat_out_ops
= { { NULL, NULL }, ip_nat_out, PF_INET, NF_IP_POST_ROUTING, NF_IP_PRI_NAT_SRC};
/* Before packet filtering, change destination */
static struct nf_hook_ops ip_nat_local_out_ops
-= { { NULL, NULL }, ip_nat_fn, PF_INET, NF_IP_LOCAL_OUT, NF_IP_PRI_NAT_DST };
+= { { NULL, NULL }, ip_nat_local_fn, PF_INET, NF_IP_LOCAL_OUT, NF_IP_PRI_NAT_DST };
/* Protocol registration. */
int ip_nat_protocol_register(struct ip_nat_protocol *proto)
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c
index 80e43d977..72b47568b 100644
--- a/net/ipv4/netfilter/ip_queue.c
+++ b/net/ipv4/netfilter/ip_queue.c
@@ -509,7 +509,7 @@ static int ipq_get_info(char *buffer, char **start, off_t offset, int length)
"Peer pid : %d\n"
"Peer died : %d\n"
"Peer copy mode : %d\n"
- "Peer copy range : %d\n"
+ "Peer copy range : %Zu\n"
"Queue length : %d\n"
"Queue max. length : %d\n"
"Queue flushing : %d\n"
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 66f47c386..73424cef8 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -39,7 +39,7 @@
#define IP_NF_ASSERT(x) \
do { \
if (!(x)) \
- printk("IPT_ASSERT: %s:%s:%u\n", \
+ printk("IP_NF_ASSERT: %s:%s:%u\n", \
__FUNCTION__, __FILE__, __LINE__); \
} while(0)
#else
@@ -683,7 +683,6 @@ check_entry(struct ipt_entry *e, const char *name, unsigned int size,
target = find_target_lock(t->u.name, &ret, &ipt_mutex);
if (!target) {
duprintf("check_entry: `%s' not found\n", t->u.name);
- up(&ipt_mutex);
return ret;
}
if (target->me)
@@ -1283,17 +1282,16 @@ ipt_register_target(struct ipt_target *target)
{
int ret;
+ MOD_INC_USE_COUNT;
ret = down_interruptible(&ipt_mutex);
if (ret != 0)
return ret;
- if (list_named_insert(&ipt_target, target)) {
- MOD_INC_USE_COUNT;
- ret = 0;
- } else {
+ if (!list_named_insert(&ipt_target, target)) {
duprintf("ipt_register_target: `%s' already in list!\n",
target->name);
ret = -EINVAL;
+ MOD_DEC_USE_COUNT;
}
up(&ipt_mutex);
return ret;
@@ -1313,16 +1311,18 @@ ipt_register_match(struct ipt_match *match)
{
int ret;
+ MOD_INC_USE_COUNT;
ret = down_interruptible(&ipt_mutex);
- if (ret != 0)
+ if (ret != 0) {
+ MOD_DEC_USE_COUNT;
return ret;
-
+ }
if (list_named_insert(&ipt_match, match)) {
- MOD_INC_USE_COUNT;
ret = 0;
} else {
duprintf("ipt_register_match: `%s' already in list!\n",
match->name);
+ MOD_DEC_USE_COUNT;
ret = -EINVAL;
}
up(&ipt_mutex);
@@ -1346,10 +1346,12 @@ int ipt_register_table(struct ipt_table *table)
static struct ipt_table_info bootstrap
= { 0, 0, { 0 }, { 0 }, { }, { } };
+ MOD_INC_USE_COUNT;
newinfo = vmalloc(sizeof(struct ipt_table_info)
+ SMP_ALIGN(table->table->size) * smp_num_cpus);
if (!newinfo) {
ret = -ENOMEM;
+ MOD_DEC_USE_COUNT;
return ret;
}
memcpy(newinfo->entries, table->table->entries, table->table->size);
@@ -1361,12 +1363,14 @@ int ipt_register_table(struct ipt_table *table)
table->table->underflow);
if (ret != 0) {
vfree(newinfo);
+ MOD_DEC_USE_COUNT;
return ret;
}
ret = down_interruptible(&ipt_mutex);
if (ret != 0) {
vfree(newinfo);
+ MOD_DEC_USE_COUNT;
return ret;
}
@@ -1386,7 +1390,6 @@ int ipt_register_table(struct ipt_table *table)
table->lock = RW_LOCK_UNLOCKED;
list_prepend(&ipt_tables, table);
- MOD_INC_USE_COUNT;
unlock:
up(&ipt_mutex);
@@ -1394,6 +1397,7 @@ int ipt_register_table(struct ipt_table *table)
free_unlock:
vfree(newinfo);
+ MOD_DEC_USE_COUNT;
goto unlock;
}
diff --git a/net/ipv4/netfilter/ipchains_core.c b/net/ipv4/netfilter/ipchains_core.c
index 419b0382c..e22898512 100644
--- a/net/ipv4/netfilter/ipchains_core.c
+++ b/net/ipv4/netfilter/ipchains_core.c
@@ -419,18 +419,10 @@ static void dump_packet(const struct iphdr *ip,
printk("%d ",f->ipfw.fw_redirpt);
}
- printk("%s PROTO=%d %d.%d.%d.%d:%hu %d.%d.%d.%d:%hu"
+ printk("%s PROTO=%d %u.%u.%u.%u:%hu %u.%u.%u.%u:%hu"
" L=%hu S=0x%2.2hX I=%hu F=0x%4.4hX T=%hu",
- ifname, ip->protocol,
- (ntohl(ip->saddr)>>24)&0xFF,
- (ntohl(ip->saddr)>>16)&0xFF,
- (ntohl(ip->saddr)>>8)&0xFF,
- (ntohl(ip->saddr))&0xFF,
- src_port,
- (ntohl(ip->daddr)>>24)&0xFF,
- (ntohl(ip->daddr)>>16)&0xFF,
- (ntohl(ip->daddr)>>8)&0xFF,
- (ntohl(ip->daddr))&0xFF,
+ ifname, ip->protocol, NIPQUAD(ip->saddr),
+ src_port, NIPQUAD(ip->daddr),
dst_port,
ntohs(ip->tot_len), ip->tos, ntohs(ip->id),
ntohs(ip->frag_off), ip->ttl);
diff --git a/net/ipv4/netfilter/ipfwadm_core.c b/net/ipv4/netfilter/ipfwadm_core.c
index a1f4e16cf..904e7c824 100644
--- a/net/ipv4/netfilter/ipfwadm_core.c
+++ b/net/ipv4/netfilter/ipfwadm_core.c
@@ -17,7 +17,7 @@
* license in recognition of the original copyright.
* -- Alan Cox.
*
- * $Id: ipfwadm_core.c,v 1.1 2000/03/17 14:42:00 davem Exp $
+ * $Id: ipfwadm_core.c,v 1.2 2000/04/15 01:48:10 davem Exp $
*
* Ported from BSD to Linux,
* Alan Cox 22/Nov/1994.
@@ -143,10 +143,7 @@
#define dprintf4(a1,a2,a3,a4)
#endif
-#define print_ip(a) printk("%d.%d.%d.%d",(ntohl(a)>>24)&0xFF,\
- (ntohl(a)>>16)&0xFF,\
- (ntohl(a)>>8)&0xFF,\
- (ntohl(a))&0xFF);
+#define print_ip(a) printk("%u.%u.%u.%u", NIPQUAD(a));
#ifdef DEBUG_IP_FIREWALL
#define dprint_ip(a) print_ip(a)
diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c
index 4675a94b8..395b1b301 100644
--- a/net/ipv4/netfilter/ipt_LOG.c
+++ b/net/ipv4/netfilter/ipt_LOG.c
@@ -38,14 +38,7 @@ static void dump_packet(const struct ipt_log_info *info,
* TOS, len, DF/MF, fragment offset, TTL, src, dst, options. */
/* Max length: 40 "SRC=255.255.255.255 DST=255.255.255.255 " */
printk("SRC=%u.%u.%u.%u DST=%u.%u.%u.%u ",
- (ntohl(iph->saddr)>>24)&0xFF,
- (ntohl(iph->saddr)>>16)&0xFF,
- (ntohl(iph->saddr)>>8)&0xFF,
- (ntohl(iph->saddr))&0xFF,
- (ntohl(iph->daddr)>>24)&0xFF,
- (ntohl(iph->daddr)>>16)&0xFF,
- (ntohl(iph->daddr)>>8)&0xFF,
- (ntohl(iph->daddr))&0xFF);
+ NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
/* Max length: 46 "LEN=65535 TOS=0xFF PREC=0xFF TTL=255 ID=65535 " */
printk("LEN=%u TOS=0x%02X PREC=0x%02X TTL=%u ID=%u ",
@@ -210,11 +203,7 @@ static void dump_packet(const struct ipt_log_info *info,
break;
case ICMP_REDIRECT:
/* Max length: 24 "GATEWAY=255.255.255.255 " */
- printk("GATEWAY=%u.%u.%u.%u ",
- (ntohl(icmph->un.gateway)>>24)&0xFF,
- (ntohl(icmph->un.gateway)>>16)&0xFF,
- (ntohl(icmph->un.gateway)>>8)&0xFF,
- (ntohl(icmph->un.gateway))&0xFF);
+ printk("GATEWAY=%u.%u.%u.%u ", NIPQUAD(icmph->un.gateway));
/* Fall through */
case ICMP_DEST_UNREACH:
case ICMP_SOURCE_QUENCH:
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
index d6a7c57f5..4d94a4cc0 100644
--- a/net/ipv4/proc.c
+++ b/net/ipv4/proc.c
@@ -7,7 +7,7 @@
* PROC file system. It is mainly used for debugging and
* statistics.
*
- * Version: $Id: proc.c,v 1.41 2000/01/21 23:45:57 davem Exp $
+ * Version: $Id: proc.c,v 1.42 2000/04/16 01:11:37 davem Exp $
*
* Authors: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
* Gerald J. Heim, <heim@peanuts.informatik.uni-tuebingen.de>
@@ -56,7 +56,7 @@ static int fold_prot_inuse(struct proto *proto)
int cpu;
for (cpu=0; cpu<smp_num_cpus; cpu++)
- res += proto->stats[cpu].inuse;
+ res += proto->stats[cpu_logical_map(cpu)].inuse;
return res;
}
@@ -99,8 +99,10 @@ static unsigned long fold_field(unsigned long *begin, int sz, int nr)
sz /= sizeof(unsigned long);
- for (i=0; i<2*smp_num_cpus; i++)
- res += begin[i*sz + nr];
+ for (i=0; i<smp_num_cpus; i++) {
+ res += begin[2*cpu_logical_map(i)*sz + nr];
+ res += begin[(2*cpu_logical_map(i)+1)*sz + nr];
+ }
return res;
}
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index e9aa1952a..a7555b6b5 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -5,7 +5,7 @@
*
* RAW - implementation of IP "raw" sockets.
*
- * Version: $Id: raw.c,v 1.48 2000/01/18 08:24:15 davem Exp $
+ * Version: $Id: raw.c,v 1.49 2000/04/25 04:13:34 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -644,26 +644,20 @@ out:
}
struct proto raw_prot = {
- raw_close, /* close */
- udp_connect, /* connect */
- udp_disconnect, /* disconnect */
- NULL, /* accept */
+ name: "RAW",
+ close: raw_close,
+ connect: udp_connect,
+ disconnect: udp_disconnect,
#ifdef CONFIG_IP_MROUTE
- ipmr_ioctl, /* ioctl */
-#else
- NULL, /* ioctl */
+ ioctl: ipmr_ioctl,
#endif
- raw_init, /* init */
- NULL, /* destroy */
- NULL, /* shutdown */
- raw_setsockopt, /* setsockopt */
- raw_getsockopt, /* getsockopt */
- raw_sendmsg, /* sendmsg */
- raw_recvmsg, /* recvmsg */
- raw_bind, /* bind */
- raw_rcv_skb, /* backlog_rcv */
- raw_v4_hash, /* hash */
- raw_v4_unhash, /* unhash */
- NULL, /* get_port */
- "RAW", /* name */
+ init: raw_init,
+ setsockopt: raw_setsockopt,
+ getsockopt: raw_getsockopt,
+ sendmsg: raw_sendmsg,
+ recvmsg: raw_recvmsg,
+ bind: raw_bind,
+ backlog_rcv: raw_rcv_skb,
+ hash: raw_v4_hash,
+ unhash: raw_v4_unhash,
};
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index afab828fb..ec254e313 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -5,7 +5,7 @@
*
* ROUTE - implementation of the IP router.
*
- * Version: $Id: route.c,v 1.83 2000/03/23 05:34:13 davem Exp $
+ * Version: $Id: route.c,v 1.86 2000/04/24 07:03:14 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -616,9 +616,9 @@ restart:
#if RT_CACHE_DEBUG >= 2
if (rt->u.rt_next) {
struct rtable * trt;
- printk("rt_cache @%02x: %08x", hash, rt->rt_dst);
+ printk("rt_cache @%02x: %u.%u.%u.%u", hash, NIPQUAD(rt->rt_dst));
for (trt=rt->u.rt_next; trt; trt=trt->u.rt_next)
- printk(" . %08x", trt->rt_dst);
+ printk(" . %u.%u.%u.%u", NIPQUAD(trt->rt_dst));
printk("\n");
}
#endif
@@ -816,10 +816,10 @@ void ip_rt_redirect(u32 old_gw, u32 daddr, u32 new_gw,
reject_redirect:
#ifdef CONFIG_IP_ROUTE_VERBOSE
if (IN_DEV_LOG_MARTIANS(in_dev) && net_ratelimit())
- printk(KERN_INFO "Redirect from %X/%s to %X ignored."
- "Path = %X -> %X, tos %02x\n",
- ntohl(old_gw), dev->name, ntohl(new_gw),
- ntohl(saddr), ntohl(daddr), tos);
+ printk(KERN_INFO "Redirect from %u.%u.%u.%u on %s about %u.%u.%u.%u ignored.\n"
+ " Advised path = %u.%u.%u.%u -> %u.%u.%u.%u, tos %02x\n",
+ NIPQUAD(old_gw), dev->name, NIPQUAD(new_gw),
+ NIPQUAD(saddr), NIPQUAD(daddr), tos);
#endif
in_dev_put(in_dev);
}
@@ -836,7 +836,8 @@ static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst)
if ((rt->rt_flags&RTCF_REDIRECTED) || rt->u.dst.expires) {
unsigned hash = rt_hash_code(rt->key.dst, rt->key.src^(rt->key.oif<<5), rt->key.tos);
#if RT_CACHE_DEBUG >= 1
- printk(KERN_DEBUG "ip_rt_advice: redirect to %d.%d.%d.%d/%02x dropped\n", NIPQUAD(rt->rt_dst), rt->key.tos);
+ printk(KERN_DEBUG "ip_rt_advice: redirect to %u.%u.%u.%u/%02x dropped\n",
+ NIPQUAD(rt->rt_dst), rt->key.tos);
#endif
rt_del(hash, rt);
return NULL;
@@ -896,8 +897,10 @@ void ip_rt_send_redirect(struct sk_buff *skb)
#ifdef CONFIG_IP_ROUTE_VERBOSE
if (IN_DEV_LOG_MARTIANS(in_dev) &&
rt->u.dst.rate_tokens == ip_rt_redirect_number && net_ratelimit())
- printk(KERN_WARNING "host %08x/if%d ignores redirects for %08x to %08x.\n",
- rt->rt_src, rt->rt_iif, rt->rt_dst, rt->rt_gateway);
+ printk(KERN_WARNING "host %u.%u.%u.%u/if%d ignores redirects for "
+ "%u.%u.%u.%u to %u.%u.%u.%u.\n",
+ NIPQUAD(rt->rt_src), rt->rt_iif,
+ NIPQUAD(rt->rt_dst), NIPQUAD(rt->rt_gateway));
#endif
}
out:
@@ -1061,8 +1064,9 @@ static void ipv4_link_failure(struct sk_buff *skb)
static int ip_rt_bug(struct sk_buff *skb)
{
- printk(KERN_DEBUG "ip_rt_bug: %08x -> %08x, %s\n", skb->nh.iph->saddr,
- skb->nh.iph->daddr, skb->dev ? skb->dev->name : "?");
+ printk(KERN_DEBUG "ip_rt_bug: %u.%u.%u.%u -> %u.%u.%u.%u, %s\n",
+ NIPQUAD(skb->nh.iph->saddr), NIPQUAD(skb->nh.iph->daddr),
+ skb->dev ? skb->dev->name : "?");
kfree_skb(skb);
return 0;
}
@@ -1499,7 +1503,8 @@ no_route:
martian_destination:
#ifdef CONFIG_IP_ROUTE_VERBOSE
if (IN_DEV_LOG_MARTIANS(in_dev) && net_ratelimit())
- printk(KERN_WARNING "martian destination %08x from %08x, dev %s\n", daddr, saddr, dev->name);
+ printk(KERN_WARNING "martian destination %u.%u.%u.%u from %u.%u.%u.%u, dev %s\n",
+ NIPQUAD(daddr), NIPQUAD(saddr), dev->name);
#endif
e_inval:
err = -EINVAL;
@@ -1513,16 +1518,20 @@ martian_source:
#ifdef CONFIG_IP_ROUTE_VERBOSE
if (IN_DEV_LOG_MARTIANS(in_dev) && net_ratelimit()) {
/*
- * RFC1812 recommenadtion, if source is martian,
+ * RFC1812 recommendation, if source is martian,
* the only hint is MAC header.
*/
- printk(KERN_WARNING "martian source %08x for %08x, dev %s\n", saddr, daddr, dev->name);
+ printk(KERN_WARNING "martian source %u.%u.%u.%u from %u.%u.%u.%u, on dev %s\n",
+ NIPQUAD(daddr), NIPQUAD(saddr), dev->name);
if (dev->hard_header_len) {
int i;
unsigned char *p = skb->mac.raw;
- printk(KERN_WARNING "ll header:");
- for (i=0; i<dev->hard_header_len; i++, p++)
- printk(" %02x", *p);
+ printk(KERN_WARNING "ll header: ");
+ for (i=0; i<dev->hard_header_len; i++, p++) {
+ printk("%02x", *p);
+ if(i<(dev->hard_header_len-1))
+ printk(":");
+ }
printk("\n");
}
}
@@ -2218,15 +2227,20 @@ static int ip_rt_acct_read(char *buffer, char **start, off_t offset,
memcpy(dst, src, length);
-#ifdef __SMP__
- if (smp_num_cpus > 1) {
+#ifdef CONFIG_SMP
+ if (smp_num_cpus > 1 || cpu_logical_map(0) != 0) {
int i;
int cnt = length/4;
- for (i=1; i<smp_num_cpus; i++) {
+ for (i=0; i<smp_num_cpus; i++) {
+ int cpu = cpu_logical_map(i);
int k;
- src += (256/4)*sizeof(struct ip_rt_acct);
+ if (cpu == 0)
+ continue;
+
+ src = (u32*)(((u8*)ip_rt_acct) + offset +
+ cpu*256*sizeof(struct ip_rt_acct));
for (k=0; k<cnt; k++)
dst[k] += src[k];
@@ -2245,7 +2259,7 @@ void __init ip_rt_init(void)
#ifdef CONFIG_NET_CLS_ROUTE
for (order=0;
- (PAGE_SIZE<<order) < 256*sizeof(ip_rt_acct)*smp_num_cpus; order++)
+ (PAGE_SIZE<<order) < 256*sizeof(ip_rt_acct)*NR_CPUS; order++)
/* NOTHING */;
ip_rt_acct = (struct ip_rt_acct *)__get_free_pages(GFP_KERNEL, order);
if (!ip_rt_acct)
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 098d91ba1..c4343b707 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -5,7 +5,7 @@
*
* Implementation of the Transmission Control Protocol(TCP).
*
- * Version: $Id: tcp.c,v 1.166 2000/03/25 01:55:11 davem Exp $
+ * Version: $Id: tcp.c,v 1.169 2000/04/20 14:41:16 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -583,9 +583,13 @@ int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg)
answ = 0;
else if (sk->urginline || !tp->urg_data ||
before(tp->urg_seq,tp->copied_seq) ||
- !before(tp->urg_seq,tp->rcv_nxt))
+ !before(tp->urg_seq,tp->rcv_nxt)) {
answ = tp->rcv_nxt - tp->copied_seq;
- else
+
+ /* Subtract 1, if FIN is in queue. */
+ if (answ && !skb_queue_empty(&sk->receive_queue))
+ answ -= ((struct sk_buff*)sk->receive_queue.prev)->h.th->fin;
+ } else
answ = tp->urg_seq - tp->copied_seq;
release_sock(sk);
break;
@@ -618,7 +622,7 @@ int tcp_listen_start(struct sock *sk)
sk->max_ack_backlog = 0;
sk->ack_backlog = 0;
- tp->accept_queue = NULL;
+ tp->accept_queue = tp->accept_queue_tail = NULL;
tp->syn_wait_lock = RW_LOCK_UNLOCKED;
lopt = kmalloc(sizeof(struct tcp_listen_opt), GFP_KERNEL);
@@ -677,7 +681,7 @@ static void tcp_listen_stop (struct sock *sk)
write_lock_bh(&tp->syn_wait_lock);
tp->listen_opt =NULL;
write_unlock_bh(&tp->syn_wait_lock);
- tp->accept_queue = NULL;
+ tp->accept_queue = tp->accept_queue_tail = NULL;
if (lopt->qlen) {
for (i=0; i<TCP_SYNQ_HSIZE; i++) {
@@ -951,10 +955,14 @@ int tcp_sendmsg(struct sock *sk, struct msghdr *msg, int size)
tmp += copy;
queue_it = 0;
}
- skb = sock_wmalloc(sk, tmp, 0, GFP_KERNEL);
- /* If we didn't get any memory, we need to sleep. */
- if (skb == NULL) {
+ if (tcp_memory_free(sk)) {
+ skb = alloc_skb(tmp, GFP_KERNEL);
+ if (skb == NULL)
+ goto do_oom;
+ skb_set_owner_w(skb, sk);
+ } else {
+ /* If we didn't get any memory, we need to sleep. */
set_bit(SOCK_ASYNC_NOSPACE, &sk->socket->flags);
set_bit(SOCK_NOSPACE, &sk->socket->flags);
@@ -1029,6 +1037,9 @@ do_shutdown:
err = -EPIPE;
}
goto out;
+do_oom:
+ err = copied ? : -ENOBUFS;
+ goto out;
do_interrupted:
if(copied)
err = copied;
@@ -2027,7 +2038,8 @@ struct sock *tcp_accept(struct sock *sk, int flags, int *err)
}
req = tp->accept_queue;
- tp->accept_queue = req->dl_next;
+ if ((tp->accept_queue = req->dl_next) == NULL)
+ tp->accept_queue_tail = NULL;
newsk = req->sk;
tcp_acceptq_removed(sk);
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 3ba12bc52..f062cb2fb 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -5,7 +5,7 @@
*
* Implementation of the Transmission Control Protocol(TCP).
*
- * Version: $Id: tcp_input.c,v 1.191 2000/03/25 01:55:13 davem Exp $
+ * Version: $Id: tcp_input.c,v 1.193 2000/04/20 14:41:16 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -1618,6 +1618,7 @@ static void tcp_fin(struct sk_buff *skb, struct sock *sk, struct tcphdr *th)
tp->fin_seq = TCP_SKB_CB(skb)->end_seq;
tp->ack.pending = 1;
+ tp->ack.quick = 0;
sk->shutdown |= RCV_SHUTDOWN;
@@ -1670,9 +1671,9 @@ static void tcp_fin(struct sk_buff *skb, struct sock *sk, struct tcphdr *th)
/* Do not send POLL_HUP for half duplex close. */
if (sk->shutdown == SHUTDOWN_MASK || sk->state == TCP_CLOSE)
- sock_wake_async(sk->socket, 1, POLL_HUP);
+ sk_wake_async(sk, 1, POLL_HUP);
else
- sock_wake_async(sk->socket, 1, POLL_IN);
+ sk_wake_async(sk, 1, POLL_IN);
}
}
@@ -2207,7 +2208,7 @@ static void tcp_check_urg(struct sock * sk, struct tcphdr * th)
kill_proc(sk->proc, SIGURG, 1);
else
kill_pg(-sk->proc, SIGURG, 1);
- sock_wake_async(sk->socket, 3, POLL_PRI);
+ sk_wake_async(sk, 3, POLL_PRI);
}
/* We may be adding urgent data when the last byte read was
@@ -2783,7 +2784,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct open_request *req,
newtp->fin_seq = req->rcv_isn;
newtp->urg_data = 0;
newtp->listen_opt = NULL;
- newtp->accept_queue = NULL;
+ newtp->accept_queue = newtp->accept_queue_tail = NULL;
/* Deinitialize syn_wait_lock to trap illegal accesses. */
memset(&newtp->syn_wait_lock, 0, sizeof(newtp->syn_wait_lock));
@@ -3162,7 +3163,7 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
if(!sk->dead) {
sk->state_change(sk);
- sock_wake_async(sk->socket, 0, POLL_OUT);
+ sk_wake_async(sk, 0, POLL_OUT);
}
if (tp->write_pending) {
@@ -3444,7 +3445,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
*/
if (!sk->dead) {
sk->state_change(sk);
- sock_wake_async(sk->socket,0,POLL_OUT);
+ sk_wake_async(sk,0,POLL_OUT);
}
tp->snd_una = TCP_SKB_CB(skb)->ack_seq;
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 3c9f4e82b..5facec2c8 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -5,7 +5,7 @@
*
* Implementation of the Transmission Control Protocol(TCP).
*
- * Version: $Id: tcp_ipv4.c,v 1.205 2000/03/26 09:16:08 davem Exp $
+ * Version: $Id: tcp_ipv4.c,v 1.207 2000/04/25 04:13:34 davem Exp $
*
* IPv4 specific functions
*
@@ -1384,7 +1384,8 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
peer->v4daddr == saddr) {
if (xtime.tv_sec < peer->tcp_ts_stamp + TCP_PAWS_MSL &&
(s32)(peer->tcp_ts - req->ts_recent) > TCP_PAWS_WINDOW) {
- NETDEBUG(printk(KERN_DEBUG "TW_REC: reject openreq %u/%u %08x/%u\n", peer->tcp_ts, req->ts_recent, saddr, ntohs(skb->h.th->source)));
+ NETDEBUG(printk(KERN_DEBUG "TW_REC: reject openreq %u/%u %u.%u.%u.%u/%u\n", \
+ peer->tcp_ts, req->ts_recent, NIPQUAD(saddr), ntohs(skb->h.th->source)));
NET_INC_STATS_BH(PAWSPassiveRejected);
dst_release(dst);
goto drop_and_free;
@@ -1402,7 +1403,9 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
* to destinations, already remembered
* to the moment of synflood.
*/
- NETDEBUG(if (net_ratelimit()) printk(KERN_DEBUG "TCP: drop open request from %08x/%u\n", saddr, ntohs(skb->h.th->source)));
+ NETDEBUG(if (net_ratelimit()) \
+ printk(KERN_DEBUG "TCP: drop open request from %u.%u.%u.%u/%u\n", \
+ NIPQUAD(saddr), ntohs(skb->h.th->source)));
TCP_INC_STATS_BH(TcpAttemptFails);
dst_release(dst);
goto drop_and_free;
@@ -2169,24 +2172,23 @@ out_no_bh:
}
struct proto tcp_prot = {
- tcp_close, /* close */
- tcp_v4_connect, /* connect */
- tcp_disconnect, /* disconnect */
- tcp_accept, /* accept */
- tcp_ioctl, /* ioctl */
- tcp_v4_init_sock, /* init */
- tcp_v4_destroy_sock, /* destroy */
- tcp_shutdown, /* shutdown */
- tcp_setsockopt, /* setsockopt */
- tcp_getsockopt, /* getsockopt */
- tcp_sendmsg, /* sendmsg */
- tcp_recvmsg, /* recvmsg */
- NULL, /* bind */
- tcp_v4_do_rcv, /* backlog_rcv */
- tcp_v4_hash, /* hash */
- tcp_unhash, /* unhash */
- tcp_v4_get_port, /* get_port */
- "TCP", /* name */
+ name: "TCP",
+ close: tcp_close,
+ connect: tcp_v4_connect,
+ disconnect: tcp_disconnect,
+ accept: tcp_accept,
+ ioctl: tcp_ioctl,
+ init: tcp_v4_init_sock,
+ destroy: tcp_v4_destroy_sock,
+ shutdown: tcp_shutdown,
+ setsockopt: tcp_setsockopt,
+ getsockopt: tcp_getsockopt,
+ sendmsg: tcp_sendmsg,
+ recvmsg: tcp_recvmsg,
+ backlog_rcv: tcp_v4_do_rcv,
+ hash: tcp_v4_hash,
+ unhash: tcp_unhash,
+ get_port: tcp_v4_get_port,
};
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 600140764..0fdb6b3f8 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -5,7 +5,7 @@
*
* Implementation of the Transmission Control Protocol(TCP).
*
- * Version: $Id: tcp_output.c,v 1.123 2000/03/25 01:52:05 davem Exp $
+ * Version: $Id: tcp_output.c,v 1.124 2000/04/08 07:21:24 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -1121,27 +1121,22 @@ void tcp_send_delayed_ack(struct sock *sk)
timeout = jiffies + ato;
/* Use new timeout only if there wasn't a older one earlier. */
- spin_lock_bh(&sk->timer_lock);
- if (!tp->delack_timer.prev || !del_timer(&tp->delack_timer)) {
- sock_hold(sk);
- tp->delack_timer.expires = timeout;
- } else {
+ if (timer_pending(&tp->delack_timer)) {
+ unsigned long old_timeout = tp->delack_timer.expires;
+
/* If delack timer was blocked or is about to expire,
* send ACK now.
*/
- if (tp->ack.blocked || time_before_eq(tp->delack_timer.expires, jiffies+(ato>>2))) {
- spin_unlock_bh(&sk->timer_lock);
-
+ if (tp->ack.blocked || time_before_eq(old_timeout, jiffies+(ato>>2))) {
tcp_send_ack(sk);
- __sock_put(sk);
return;
}
- if (time_before(timeout, tp->delack_timer.expires))
- tp->delack_timer.expires = timeout;
+ if (!time_before(timeout, old_timeout))
+ timeout = old_timeout;
}
- add_timer(&tp->delack_timer);
- spin_unlock_bh(&sk->timer_lock);
+ if (!mod_timer(&tp->delack_timer, timeout))
+ sock_hold(sk);
#ifdef TCP_FORMAL_WINDOW
/* Explanation. Header prediction path does not handle
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
index 6b3695c3e..9e9887707 100644
--- a/net/ipv4/tcp_timer.c
+++ b/net/ipv4/tcp_timer.c
@@ -5,7 +5,7 @@
*
* Implementation of the Transmission Control Protocol(TCP).
*
- * Version: $Id: tcp_timer.c,v 1.74 2000/02/14 20:56:30 davem Exp $
+ * Version: $Id: tcp_timer.c,v 1.75 2000/04/08 07:21:25 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -49,8 +49,6 @@ void tcp_init_xmit_timers(struct sock *sk)
{
struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
- spin_lock_init(&sk->timer_lock);
-
init_timer(&tp->retransmit_timer);
tp->retransmit_timer.function=&tcp_retransmit_timer;
tp->retransmit_timer.data = (unsigned long) sk;
@@ -76,7 +74,6 @@ void tcp_reset_xmit_timer(struct sock *sk, int what, unsigned long when)
{
struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
- spin_lock_bh(&sk->timer_lock);
switch (what) {
case TCP_TIME_RETRANS:
/* When seting the transmit timer the probe timer
@@ -84,50 +81,44 @@ void tcp_reset_xmit_timer(struct sock *sk, int what, unsigned long when)
* The delayed ack timer can be set if we are changing the
* retransmit timer when removing acked frames.
*/
- if(tp->probe_timer.prev && del_timer(&tp->probe_timer))
+ if (timer_pending(&tp->probe_timer) && del_timer(&tp->probe_timer))
__sock_put(sk);
- if (!tp->retransmit_timer.prev || !del_timer(&tp->retransmit_timer))
- sock_hold(sk);
if (when > TCP_RTO_MAX) {
printk(KERN_DEBUG "reset_xmit_timer sk=%p when=0x%lx, caller=%p\n", sk, when, NET_CALLER(sk));
when = TCP_RTO_MAX;
}
- mod_timer(&tp->retransmit_timer, jiffies+when);
+ if (!mod_timer(&tp->retransmit_timer, jiffies+when))
+ sock_hold(sk);
break;
case TCP_TIME_DACK:
- if (!tp->delack_timer.prev || !del_timer(&tp->delack_timer))
+ if (!mod_timer(&tp->delack_timer, jiffies+when))
sock_hold(sk);
- mod_timer(&tp->delack_timer, jiffies+when);
break;
case TCP_TIME_PROBE0:
- if (!tp->probe_timer.prev || !del_timer(&tp->probe_timer))
+ if (!mod_timer(&tp->probe_timer, jiffies+when))
sock_hold(sk);
- mod_timer(&tp->probe_timer, jiffies+when);
- break;
+ break;
default:
printk(KERN_DEBUG "bug: unknown timer value\n");
};
- spin_unlock_bh(&sk->timer_lock);
}
void tcp_clear_xmit_timers(struct sock *sk)
{
struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
- spin_lock_bh(&sk->timer_lock);
- if(tp->retransmit_timer.prev && del_timer(&tp->retransmit_timer))
+ if(timer_pending(&tp->retransmit_timer) && del_timer(&tp->retransmit_timer))
__sock_put(sk);
- if(tp->delack_timer.prev && del_timer(&tp->delack_timer))
+ if(timer_pending(&tp->delack_timer) && del_timer(&tp->delack_timer))
__sock_put(sk);
tp->ack.blocked = 0;
- if(tp->probe_timer.prev && del_timer(&tp->probe_timer))
+ if(timer_pending(&tp->probe_timer) && del_timer(&tp->probe_timer))
__sock_put(sk);
- if(sk->timer.prev && del_timer(&sk->timer))
+ if(timer_pending(&sk->timer) && del_timer(&sk->timer))
__sock_put(sk);
- spin_unlock_bh(&sk->timer_lock);
}
static void tcp_write_err(struct sock *sk)
@@ -138,6 +129,35 @@ static void tcp_write_err(struct sock *sk)
tcp_done(sk);
}
+/* Do not allow orphaned sockets to eat all our resources.
+ * This is direct violation of TCP specs, but it is required
+ * to prevent DoS attacks. It is called when a retransmission timeout
+ * or zero probe timeout occurs on orphaned socket.
+ *
+ * Criterium is still not confirmed experimentally and may change.
+ * We kill the socket, if:
+ * 1. If number of orphaned sockets exceeds an administratively configured
+ * limit.
+ * 2. Under pessimistic assumption that all the orphans eat memory not
+ * less than this one, total consumed memory exceeds all
+ * the available memory.
+ */
+static int tcp_out_of_resources(struct sock *sk, int do_reset)
+{
+ int orphans = atomic_read(&tcp_orphan_count);
+
+ if (orphans >= sysctl_tcp_max_orphans ||
+ ((orphans*atomic_read(&sk->wmem_alloc))>>PAGE_SHIFT) >= num_physpages) {
+ if (net_ratelimit())
+ printk(KERN_INFO "Out of socket memory\n");
+ if (do_reset)
+ tcp_send_active_reset(sk, GFP_ATOMIC);
+ tcp_done(sk);
+ return 1;
+ }
+ return 0;
+}
+
/* A write timeout has occurred. Process the after effects. */
static int tcp_write_timeout(struct sock *sk)
{
@@ -172,9 +192,14 @@ static int tcp_write_timeout(struct sock *sk)
dst_negative_advice(&sk->dst_cache);
}
+
retry_until = sysctl_tcp_retries2;
- if (sk->dead)
+ if (sk->dead) {
+ if (tcp_out_of_resources(sk, tp->retransmits < retry_until))
+ return 1;
+
retry_until = sysctl_tcp_orphan_retries;
+ }
}
if (tp->retransmits >= retry_until) {
@@ -257,7 +282,14 @@ static void tcp_probe_timer(unsigned long data)
* with RFCs, only probe timer combines both retransmission timeout
* and probe timeout in one bottle. --ANK
*/
- max_probes = sk->dead ? sysctl_tcp_orphan_retries : sysctl_tcp_retries2;
+ max_probes = sysctl_tcp_retries2;
+
+ if (sk->dead) {
+ if (tcp_out_of_resources(sk, tp->probes_out <= max_probes))
+ goto out_unlock;
+
+ max_probes = sysctl_tcp_orphan_retries;
+ }
if (tp->probes_out > max_probes) {
tcp_write_err(sk);
@@ -574,6 +606,8 @@ static void tcp_retransmit_timer(unsigned long data)
tp->retransmits++;
tp->rto = min(tp->rto << 1, TCP_RTO_MAX);
tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS, tp->rto);
+ if (tp->retransmits > sysctl_tcp_retries1)
+ __sk_dst_reset(sk);
TCP_CHECK_TIMER(sk);
out_unlock:
@@ -676,19 +710,14 @@ static void tcp_synack_timer(struct sock *sk)
void tcp_delete_keepalive_timer (struct sock *sk)
{
- spin_lock_bh(&sk->timer_lock);
- if (sk->timer.prev && del_timer (&sk->timer))
+ if (timer_pending(&sk->timer) && del_timer (&sk->timer))
__sock_put(sk);
- spin_unlock_bh(&sk->timer_lock);
}
void tcp_reset_keepalive_timer (struct sock *sk, unsigned long len)
{
- spin_lock_bh(&sk->timer_lock);
- if(!sk->timer.prev || !del_timer(&sk->timer))
+ if (!mod_timer(&sk->timer, jiffies+len))
sock_hold(sk);
- mod_timer(&sk->timer, jiffies+len);
- spin_unlock_bh(&sk->timer_lock);
}
void tcp_set_keepalive(struct sock *sk, int val)
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index e188b4997..570e1de2b 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -5,7 +5,7 @@
*
* The User Datagram Protocol (UDP).
*
- * Version: $Id: udp.c,v 1.80 2000/02/27 19:51:43 davem Exp $
+ * Version: $Id: udp.c,v 1.81 2000/04/25 04:13:34 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -1041,22 +1041,17 @@ out:
}
struct proto udp_prot = {
- udp_close, /* close */
- udp_connect, /* connect */
- udp_disconnect, /* disconnect */
- NULL, /* accept */
- udp_ioctl, /* ioctl */
- NULL, /* init */
- NULL, /* destroy */
- NULL, /* shutdown */
- ip_setsockopt, /* setsockopt */
- ip_getsockopt, /* getsockopt */
- udp_sendmsg, /* sendmsg */
- udp_recvmsg, /* recvmsg */
- NULL, /* bind */
- udp_queue_rcv_skb, /* backlog_rcv */
- udp_v4_hash, /* hash */
- udp_v4_unhash, /* unhash */
- udp_v4_get_port, /* good_socknum */
- "UDP", /* name */
+ name: "UDP",
+ close: udp_close,
+ connect: udp_connect,
+ disconnect: udp_disconnect,
+ ioctl: udp_ioctl,
+ setsockopt: ip_setsockopt,
+ getsockopt: ip_getsockopt,
+ sendmsg: udp_sendmsg,
+ recvmsg: udp_recvmsg,
+ backlog_rcv: udp_queue_rcv_skb,
+ hash: udp_v4_hash,
+ unhash: udp_v4_unhash,
+ get_port: udp_v4_get_port,
};
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 919abf4f9..8b039a658 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -7,7 +7,7 @@
*
* Adapted from linux/net/ipv4/af_inet.c
*
- * $Id: af_inet6.c,v 1.55 2000/02/27 19:51:47 davem Exp $
+ * $Id: af_inet6.c,v 1.56 2000/04/25 04:13:34 davem Exp $
*
* Fixes:
* Hideaki YOSHIFUJI : sin6_scope_id support
@@ -445,45 +445,43 @@ static int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
}
struct proto_ops inet6_stream_ops = {
- PF_INET6,
-
- inet6_release,
- inet6_bind,
- inet_stream_connect, /* ok */
- sock_no_socketpair, /* a do nothing */
- inet_accept, /* ok */
- inet6_getname,
- tcp_poll, /* ok */
- inet6_ioctl, /* must change */
- inet_listen, /* ok */
- inet_shutdown, /* ok */
- inet_setsockopt, /* ok */
- inet_getsockopt, /* ok */
- sock_no_fcntl, /* ok */
- inet_sendmsg, /* ok */
- inet_recvmsg, /* ok */
- sock_no_mmap
+ family: PF_INET6,
+
+ release: inet6_release,
+ bind: inet6_bind,
+ connect: inet_stream_connect, /* ok */
+ socketpair: sock_no_socketpair, /* a do nothing */
+ accept: inet_accept, /* ok */
+ getname: inet6_getname,
+ poll: tcp_poll, /* ok */
+ ioctl: inet6_ioctl, /* must change */
+ listen: inet_listen, /* ok */
+ shutdown: inet_shutdown, /* ok */
+ setsockopt: inet_setsockopt, /* ok */
+ getsockopt: inet_getsockopt, /* ok */
+ sendmsg: inet_sendmsg, /* ok */
+ recvmsg: inet_recvmsg, /* ok */
+ mmap: sock_no_mmap,
};
struct proto_ops inet6_dgram_ops = {
- PF_INET6,
-
- inet6_release,
- inet6_bind,
- inet_dgram_connect, /* ok */
- sock_no_socketpair, /* a do nothing */
- sock_no_accept, /* a do nothing */
- inet6_getname,
- datagram_poll, /* ok */
- inet6_ioctl, /* must change */
- sock_no_listen, /* ok */
- inet_shutdown, /* ok */
- inet_setsockopt, /* ok */
- inet_getsockopt, /* ok */
- sock_no_fcntl, /* ok */
- inet_sendmsg, /* ok */
- inet_recvmsg, /* ok */
- sock_no_mmap,
+ family: PF_INET6,
+
+ release: inet6_release,
+ bind: inet6_bind,
+ connect: inet_dgram_connect, /* ok */
+ socketpair: sock_no_socketpair, /* a do nothing */
+ accept: sock_no_accept, /* a do nothing */
+ getname: inet6_getname,
+ poll: datagram_poll, /* ok */
+ ioctl: inet6_ioctl, /* must change */
+ listen: sock_no_listen, /* ok */
+ shutdown: inet_shutdown, /* ok */
+ setsockopt: inet_setsockopt, /* ok */
+ getsockopt: inet_getsockopt, /* ok */
+ sendmsg: inet_sendmsg, /* ok */
+ recvmsg: inet_recvmsg, /* ok */
+ mmap: sock_no_mmap,
};
struct net_proto_family inet6_family_ops = {
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c
index c9be23990..22c1fa367 100644
--- a/net/ipv6/proc.c
+++ b/net/ipv6/proc.c
@@ -7,7 +7,7 @@
* PROC file system. This is very similar to the IPv4 version,
* except it reports the sockets in the INET6 address family.
*
- * Version: $Id: proc.c,v 1.13 2000/01/09 02:19:55 davem Exp $
+ * Version: $Id: proc.c,v 1.14 2000/04/16 01:11:37 davem Exp $
*
* Authors: David S. Miller (davem@caip.rutgers.edu)
*
@@ -32,7 +32,7 @@ static int fold_prot_inuse(struct proto *proto)
int cpu;
for (cpu=0; cpu<smp_num_cpus; cpu++)
- res += proto->stats[cpu].inuse;
+ res += proto->stats[cpu_logical_map(cpu)].inuse;
return res;
}
@@ -138,8 +138,10 @@ static unsigned long fold_field(unsigned long *ptr, int size)
unsigned long res = 0;
int i;
- for (i=0; i<smp_num_cpus; i++)
- res += ptr[i*size];
+ for (i=0; i<smp_num_cpus; i++) {
+ res += ptr[2*cpu_logical_map(i)*size];
+ res += ptr[(2*cpu_logical_map(i)+1)*size];
+ }
return res;
}
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index bb4ecb551..6abd7f4bf 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -7,7 +7,7 @@
*
* Adapted from linux/net/ipv4/raw.c
*
- * $Id: raw.c,v 1.34 2000/02/27 19:51:48 davem Exp $
+ * $Id: raw.c,v 1.35 2000/04/25 04:13:34 davem Exp $
*
* Fixes:
* Hideaki YOSHIFUJI : sin6_scope_id support
@@ -786,22 +786,18 @@ out:
}
struct proto rawv6_prot = {
- rawv6_close, /* close */
- udpv6_connect, /* connect */
- udp_disconnect, /* disconnect */
- NULL, /* accept */
- NULL, /* ioctl */
- rawv6_init_sk, /* init */
- inet6_destroy_sock, /* destroy */
- NULL, /* shutdown */
- rawv6_setsockopt, /* setsockopt */
- rawv6_getsockopt, /* getsockopt */
- rawv6_sendmsg, /* sendmsg */
- rawv6_recvmsg, /* recvmsg */
- rawv6_bind, /* bind */
- rawv6_rcv_skb, /* backlog_rcv */
- raw_v6_hash, /* hash */
- raw_v6_unhash, /* unhash */
- NULL, /* get_port */
- "RAW", /* name */
+ name: "RAW",
+ close: rawv6_close,
+ connect: udpv6_connect,
+ disconnect: udp_disconnect,
+ init: rawv6_init_sk,
+ destroy: inet6_destroy_sock,
+ setsockopt: rawv6_setsockopt,
+ getsockopt: rawv6_getsockopt,
+ sendmsg: rawv6_sendmsg,
+ recvmsg: rawv6_recvmsg,
+ bind: rawv6_bind,
+ backlog_rcv: rawv6_rcv_skb,
+ hash: raw_v6_hash,
+ unhash: raw_v6_unhash,
};
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index c6fd03355..760c77cd8 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -5,7 +5,7 @@
* Authors:
* Pedro Roque <roque@di.fc.ul.pt>
*
- * $Id: tcp_ipv6.c,v 1.122 2000/03/25 01:52:11 davem Exp $
+ * $Id: tcp_ipv6.c,v 1.123 2000/04/25 04:13:34 davem Exp $
*
* Based on:
* linux/net/ipv4/tcp.c
@@ -2080,24 +2080,23 @@ out_no_bh:
}
struct proto tcpv6_prot = {
- tcp_close, /* close */
- tcp_v6_connect, /* connect */
- tcp_disconnect, /* disconnect */
- tcp_accept, /* accept */
- tcp_ioctl, /* ioctl */
- tcp_v6_init_sock, /* init */
- tcp_v6_destroy_sock, /* destroy */
- tcp_shutdown, /* shutdown */
- tcp_setsockopt, /* setsockopt */
- tcp_getsockopt, /* getsockopt */
- tcp_sendmsg, /* sendmsg */
- tcp_recvmsg, /* recvmsg */
- NULL, /* bind */
- tcp_v6_do_rcv, /* backlog_rcv */
- tcp_v6_hash, /* hash */
- tcp_unhash, /* unhash */
- tcp_v6_get_port, /* get_port */
- "TCPv6", /* name */
+ name: "TCPv6",
+ close: tcp_close,
+ connect: tcp_v6_connect,
+ disconnect: tcp_disconnect,
+ accept: tcp_accept,
+ ioctl: tcp_ioctl,
+ init: tcp_v6_init_sock,
+ destroy: tcp_v6_destroy_sock,
+ shutdown: tcp_shutdown,
+ setsockopt: tcp_setsockopt,
+ getsockopt: tcp_getsockopt,
+ sendmsg: tcp_sendmsg,
+ recvmsg: tcp_recvmsg,
+ backlog_rcv: tcp_v6_do_rcv,
+ hash: tcp_v6_hash,
+ unhash: tcp_unhash,
+ get_port: tcp_v6_get_port,
};
static struct inet6_protocol tcpv6_protocol =
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index fed8e3aa2..5665c3225 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -7,7 +7,7 @@
*
* Based on linux/ipv4/udp.c
*
- * $Id: udp.c,v 1.51 2000/02/27 19:51:51 davem Exp $
+ * $Id: udp.c,v 1.52 2000/04/25 04:13:34 davem Exp $
*
* Fixes:
* Hideaki YOSHIFUJI : sin6_scope_id support
@@ -972,24 +972,20 @@ out:
}
struct proto udpv6_prot = {
- udpv6_close, /* close */
- udpv6_connect, /* connect */
- udp_disconnect, /* disconnect */
- NULL, /* accept */
- udp_ioctl, /* ioctl */
- NULL, /* init */
- inet6_destroy_sock, /* destroy */
- NULL, /* shutdown */
- ipv6_setsockopt, /* setsockopt */
- ipv6_getsockopt, /* getsockopt */
- udpv6_sendmsg, /* sendmsg */
- udpv6_recvmsg, /* recvmsg */
- NULL, /* bind */
- udpv6_queue_rcv_skb, /* backlog_rcv */
- udp_v6_hash, /* hash */
- udp_v6_unhash, /* unhash */
- udp_v6_get_port, /* get_port */
- "UDP", /* name */
+ name: "UDP",
+ close: udpv6_close,
+ connect: udpv6_connect,
+ disconnect: udp_disconnect,
+ ioctl: udp_ioctl,
+ destroy: inet6_destroy_sock,
+ setsockopt: ipv6_setsockopt,
+ getsockopt: ipv6_getsockopt,
+ sendmsg: udpv6_sendmsg,
+ recvmsg: udpv6_recvmsg,
+ backlog_rcv: udpv6_queue_rcv_skb,
+ hash: udp_v6_hash,
+ unhash: udp_v6_unhash,
+ get_port: udp_v6_get_port,
};
void __init udpv6_init(void)
diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c
index 9db90b0b8..e4c178560 100644
--- a/net/ipx/af_ipx.c
+++ b/net/ipx/af_ipx.c
@@ -2330,23 +2330,23 @@ static struct net_proto_family ipx_family_ops = {
};
static struct proto_ops SOCKOPS_WRAPPED(ipx_dgram_ops) = {
- PF_IPX,
- ipx_release,
- ipx_bind,
- ipx_connect,
- sock_no_socketpair,
- sock_no_accept,
- ipx_getname,
- datagram_poll,
- ipx_ioctl,
- sock_no_listen,
- sock_no_shutdown, /* FIXME: We have to really support shutdown. */
- ipx_setsockopt,
- ipx_getsockopt,
- sock_no_fcntl,
- ipx_sendmsg,
- ipx_recvmsg,
- sock_no_mmap
+ family: PF_IPX,
+
+ release: ipx_release,
+ bind: ipx_bind,
+ connect: ipx_connect,
+ socketpair: sock_no_socketpair,
+ accept: sock_no_accept,
+ getname: ipx_getname,
+ poll: datagram_poll,
+ ioctl: ipx_ioctl,
+ listen: sock_no_listen,
+ shutdown: sock_no_shutdown, /* FIXME: We have to really support shutdown. */
+ setsockopt: ipx_setsockopt,
+ getsockopt: ipx_getsockopt,
+ sendmsg: ipx_sendmsg,
+ recvmsg: ipx_recvmsg,
+ mmap: sock_no_mmap,
};
#include <linux/smp_lock.h>
diff --git a/net/ipx/af_spx.c b/net/ipx/af_spx.c
index 1eb7a725c..75aaaa34a 100644
--- a/net/ipx/af_spx.c
+++ b/net/ipx/af_spx.c
@@ -884,23 +884,23 @@ static int spx_getsockopt(struct socket *sock, int level, int optname,
}
static struct proto_ops SOCKOPS_WRAPPED(spx_ops) = {
- PF_IPX,
- spx_release,
- spx_bind,
- spx_connect,
- sock_no_socketpair,
- spx_accept,
- spx_getname,
- spx_datagram_poll,
- spx_ioctl,
- spx_listen,
- sock_no_shutdown,
- spx_setsockopt,
- spx_getsockopt,
- sock_no_fcntl,
- spx_sendmsg,
- spx_recvmsg,
- sock_no_mmap
+ family: PF_IPX,
+
+ release: spx_release,
+ bind: spx_bind,
+ connect: spx_connect,
+ socketpair: sock_no_socketpair,
+ accept: spx_accept,
+ getname: spx_getname,
+ poll: spx_datagram_poll,
+ ioctl: spx_ioctl,
+ listen: spx_listen,
+ shutdown: sock_no_shutdown,
+ setsockopt: spx_setsockopt,
+ getsockopt: spx_getsockopt,
+ sendmsg: spx_sendmsg,
+ recvmsg: spx_recvmsg,
+ mmap: sock_no_mmap,
};
#include <linux/smp_lock.h>
diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c
index bed8c5cc2..2ba86afcc 100644
--- a/net/irda/af_irda.c
+++ b/net/irda/af_irda.c
@@ -1215,9 +1215,9 @@ static int irda_recvmsg_dgram(struct socket *sock, struct msghdr *msg,
static void irda_data_wait(struct sock *sk)
{
if (!skb_peek(&sk->receive_queue)) {
- sk->socket->flags |= SO_WAITDATA;
+ set_bit(SOCK_ASYNC_WAITDATA, &sk->socket->flags);
interruptible_sleep_on(sk->sleep);
- sk->socket->flags &= ~SO_WAITDATA;
+ clear_bit(SOCK_ASYNC_WAITDATA, &sk->socket->flags);
}
}
@@ -1241,7 +1241,7 @@ static int irda_recvmsg_stream(struct socket *sock, struct msghdr *msg,
self = sk->protinfo.irda;
ASSERT(self != NULL, return -1;);
- if (sock->flags & SO_ACCEPTCON)
+ if (sock->flags & __SO_ACCEPTCON)
return(-EINVAL);
if (flags & MSG_OOB)
@@ -2015,88 +2015,84 @@ static struct net_proto_family irda_family_ops =
};
static struct proto_ops SOCKOPS_WRAPPED(irda_stream_ops) = {
- PF_IRDA,
+ family: PF_IRDA,
- irda_release,
- irda_bind,
- irda_connect,
- sock_no_socketpair,
- irda_accept,
- irda_getname,
- irda_poll,
- irda_ioctl,
- irda_listen,
- irda_shutdown,
- irda_setsockopt,
- irda_getsockopt,
- sock_no_fcntl,
- irda_sendmsg,
- irda_recvmsg_stream,
- sock_no_mmap
+ release: irda_release,
+ bind: irda_bind,
+ connect: irda_connect,
+ socketpair: sock_no_socketpair,
+ accept: irda_accept,
+ getname: irda_getname,
+ poll: irda_poll,
+ ioctl: irda_ioctl,
+ listen: irda_listen,
+ shutdown: irda_shutdown,
+ setsockopt: irda_setsockopt,
+ getsockopt: irda_getsockopt,
+ sendmsg: irda_sendmsg,
+ recvmsg: irda_recvmsg_stream,
+ mmap: sock_no_mmap,
};
static struct proto_ops SOCKOPS_WRAPPED(irda_seqpacket_ops) = {
- PF_IRDA,
+ family: PF_IRDA,
- irda_release,
- irda_bind,
- irda_connect,
- sock_no_socketpair,
- irda_accept,
- irda_getname,
- datagram_poll,
- irda_ioctl,
- irda_listen,
- irda_shutdown,
- irda_setsockopt,
- irda_getsockopt,
- sock_no_fcntl,
- irda_sendmsg,
- irda_recvmsg_dgram,
- sock_no_mmap,
+ release: irda_release,
+ bind: irda_bind,
+ connect: irda_connect,
+ socketpair: sock_no_socketpair,
+ accept: irda_accept,
+ getname: irda_getname,
+ poll: datagram_poll,
+ ioctl: irda_ioctl,
+ listen: irda_listen,
+ shutdown: irda_shutdown,
+ setsockopt: irda_setsockopt,
+ getsockopt: irda_getsockopt,
+ sendmsg: irda_sendmsg,
+ recvmsg: irda_recvmsg_dgram,
+ mmap: sock_no_mmap,
};
static struct proto_ops SOCKOPS_WRAPPED(irda_dgram_ops) = {
- PF_IRDA,
+ family: PF_IRDA,
- irda_release,
- irda_bind,
- irda_connect,
- sock_no_socketpair,
- irda_accept,
- irda_getname,
- datagram_poll,
- irda_ioctl,
- irda_listen,
- irda_shutdown,
- irda_setsockopt,
- irda_getsockopt,
- sock_no_fcntl,
- irda_sendmsg_dgram,
- irda_recvmsg_dgram,
- sock_no_mmap,
+ release: irda_release,
+ bind: irda_bind,
+ connect: irda_connect,
+ socketpair: sock_no_socketpair,
+ accept: irda_accept,
+ getname: irda_getname,
+ poll: datagram_poll,
+ ioctl: irda_ioctl,
+ listen: irda_listen,
+ shutdown: irda_shutdown,
+ setsockopt: irda_setsockopt,
+ getsockopt: irda_getsockopt,
+ sendmsg: irda_sendmsg_dgram,
+ recvmsg: irda_recvmsg_dgram,
+ mmap: sock_no_mmap,
};
#ifdef CONFIG_IRDA_ULTRA
static struct proto_ops SOCKOPS_WRAPPED(irda_ultra_ops) = {
- PF_IRDA,
+ family: PF_IRDA,
- irda_release,
- irda_bind,
- sock_no_connect,
- sock_no_socketpair,
- sock_no_accept,
- irda_getname,
- datagram_poll,
- irda_ioctl,
- sock_no_listen,
- irda_shutdown,
- irda_setsockopt,
- irda_getsockopt,
- sock_no_fcntl,
- irda_sendmsg_ultra,
- irda_recvmsg_dgram,
- sock_no_mmap,
+ release: irda_release,
+ bind: irda_bind,
+ connect: sock_no_connect,
+ socketpair: sock_no_socketpair,
+ accept: sock_no_accept,
+ getname: irda_getname,
+ poll: datagram_poll,
+ ioctl: irda_ioctl,
+ listen: sock_no_listen,
+ shutdown: irda_shutdown,
+ setsockopt: irda_setsockopt,
+ getsockopt: irda_getsockopt,
+ sendmsg: irda_sendmsg_ultra,
+ recvmsg: irda_recvmsg_dgram,
+ mmap: sock_no_mmap,
};
#endif /* CONFIG_IRDA_ULTRA */
diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c
index ac70091af..d785983da 100644
--- a/net/irda/ircomm/ircomm_tty.c
+++ b/net/irda/ircomm/ircomm_tty.c
@@ -1346,7 +1346,7 @@ static int ircomm_tty_read_proc(char *buf, char **start, off_t offset, int len,
done:
if (offset >= count+begin)
return 0;
- *start = buf + (begin-offset);
+ *start = buf + (offset-begin);
return ((len < begin+count-offset) ? len : begin+count-offset);
}
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index b76a07274..4f4263d56 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -941,24 +941,23 @@ done:
#endif
struct proto_ops netlink_ops = {
- PF_NETLINK,
-
- netlink_release,
- netlink_bind,
- netlink_connect,
- sock_no_socketpair,
- sock_no_accept,
- netlink_getname,
- datagram_poll,
- sock_no_ioctl,
- sock_no_listen,
- sock_no_shutdown,
- sock_no_setsockopt,
- sock_no_getsockopt,
- sock_no_fcntl,
- netlink_sendmsg,
- netlink_recvmsg,
- sock_no_mmap
+ family: PF_NETLINK,
+
+ release: netlink_release,
+ bind: netlink_bind,
+ connect: netlink_connect,
+ socketpair: sock_no_socketpair,
+ accept: sock_no_accept,
+ getname: netlink_getname,
+ poll: datagram_poll,
+ ioctl: sock_no_ioctl,
+ listen: sock_no_listen,
+ shutdown: sock_no_shutdown,
+ setsockopt: sock_no_setsockopt,
+ getsockopt: sock_no_getsockopt,
+ sendmsg: netlink_sendmsg,
+ recvmsg: netlink_recvmsg,
+ mmap: sock_no_mmap,
};
struct net_proto_family netlink_family_ops = {
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
index acdea4c9c..3aa133d02 100644
--- a/net/netrom/af_netrom.c
+++ b/net/netrom/af_netrom.c
@@ -1240,24 +1240,23 @@ static struct net_proto_family nr_family_ops =
};
static struct proto_ops SOCKOPS_WRAPPED(nr_proto_ops) = {
- PF_NETROM,
-
- nr_release,
- nr_bind,
- nr_connect,
- sock_no_socketpair,
- nr_accept,
- nr_getname,
- datagram_poll,
- nr_ioctl,
- nr_listen,
- sock_no_shutdown,
- nr_setsockopt,
- nr_getsockopt,
- sock_no_fcntl,
- nr_sendmsg,
- nr_recvmsg,
- sock_no_mmap
+ family: PF_NETROM,
+
+ release: nr_release,
+ bind: nr_bind,
+ connect: nr_connect,
+ socketpair: sock_no_socketpair,
+ accept: nr_accept,
+ getname: nr_getname,
+ poll: datagram_poll,
+ ioctl: nr_ioctl,
+ listen: nr_listen,
+ shutdown: sock_no_shutdown,
+ setsockopt: nr_setsockopt,
+ getsockopt: nr_getsockopt,
+ sendmsg: nr_sendmsg,
+ recvmsg: nr_recvmsg,
+ mmap: sock_no_mmap,
};
#include <linux/smp_lock.h>
diff --git a/net/netsyms.c b/net/netsyms.c
index 9a7030d7e..1b22129b8 100644
--- a/net/netsyms.c
+++ b/net/netsyms.c
@@ -134,7 +134,6 @@ EXPORT_SYMBOL(sock_no_listen);
EXPORT_SYMBOL(sock_no_shutdown);
EXPORT_SYMBOL(sock_no_getsockopt);
EXPORT_SYMBOL(sock_no_setsockopt);
-EXPORT_SYMBOL(sock_no_fcntl);
EXPORT_SYMBOL(sock_no_sendmsg);
EXPORT_SYMBOL(sock_no_recvmsg);
EXPORT_SYMBOL(sock_no_mmap);
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 799ec9476..2955a04f6 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -5,7 +5,7 @@
*
* PACKET - implements raw packet sockets.
*
- * Version: $Id: af_packet.c,v 1.33 2000/03/13 22:11:50 davem Exp $
+ * Version: $Id: af_packet.c,v 1.34 2000/04/25 04:13:35 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -1723,46 +1723,44 @@ out:
#ifdef CONFIG_SOCK_PACKET
struct proto_ops packet_ops_spkt = {
- PF_PACKET,
-
- packet_release,
- packet_bind_spkt,
- sock_no_connect,
- sock_no_socketpair,
- sock_no_accept,
- packet_getname_spkt,
- datagram_poll,
- packet_ioctl,
- sock_no_listen,
- sock_no_shutdown,
- sock_no_setsockopt,
- sock_no_getsockopt,
- sock_no_fcntl,
- packet_sendmsg_spkt,
- packet_recvmsg,
- sock_no_mmap
+ family: PF_PACKET,
+
+ release: packet_release,
+ bind: packet_bind_spkt,
+ connect: sock_no_connect,
+ socketpair: sock_no_socketpair,
+ accept: sock_no_accept,
+ getname: packet_getname_spkt,
+ poll: datagram_poll,
+ ioctl: packet_ioctl,
+ listen: sock_no_listen,
+ shutdown: sock_no_shutdown,
+ setsockopt: sock_no_setsockopt,
+ getsockopt: sock_no_getsockopt,
+ sendmsg: packet_sendmsg_spkt,
+ recvmsg: packet_recvmsg,
+ mmap: sock_no_mmap,
};
#endif
struct proto_ops packet_ops = {
- PF_PACKET,
-
- packet_release,
- packet_bind,
- sock_no_connect,
- sock_no_socketpair,
- sock_no_accept,
- packet_getname,
- packet_poll,
- packet_ioctl,
- sock_no_listen,
- sock_no_shutdown,
- packet_setsockopt,
- packet_getsockopt,
- sock_no_fcntl,
- packet_sendmsg,
- packet_recvmsg,
- packet_mmap,
+ family: PF_PACKET,
+
+ release: packet_release,
+ bind: packet_bind,
+ connect: sock_no_connect,
+ socketpair: sock_no_socketpair,
+ accept: sock_no_accept,
+ getname: packet_getname,
+ poll: packet_poll,
+ ioctl: packet_ioctl,
+ listen: sock_no_listen,
+ shutdown: sock_no_shutdown,
+ setsockopt: packet_setsockopt,
+ getsockopt: packet_getsockopt,
+ sendmsg: packet_sendmsg,
+ recvmsg: packet_recvmsg,
+ mmap: packet_mmap,
};
static struct net_proto_family packet_family_ops = {
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c
index 93f1a40ab..f91baa2eb 100644
--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -1410,24 +1410,23 @@ static struct net_proto_family rose_family_ops = {
};
static struct proto_ops SOCKOPS_WRAPPED(rose_proto_ops) = {
- PF_ROSE,
-
- rose_release,
- rose_bind,
- rose_connect,
- sock_no_socketpair,
- rose_accept,
- rose_getname,
- datagram_poll,
- rose_ioctl,
- rose_listen,
- sock_no_shutdown,
- rose_setsockopt,
- rose_getsockopt,
- sock_no_fcntl,
- rose_sendmsg,
- rose_recvmsg,
- sock_no_mmap
+ family: PF_ROSE,
+
+ release: rose_release,
+ bind: rose_bind,
+ connect: rose_connect,
+ socketpair: sock_no_socketpair,
+ accept: rose_accept,
+ getname: rose_getname,
+ poll: datagram_poll,
+ ioctl: rose_ioctl,
+ listen: rose_listen,
+ shutdown: sock_no_shutdown,
+ setsockopt: rose_setsockopt,
+ getsockopt: rose_getsockopt,
+ sendmsg: rose_sendmsg,
+ recvmsg: rose_recvmsg,
+ mmap: sock_no_mmap,
};
#include <linux/smp_lock.h>
diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c
index e463b33ca..abf0bac91 100644
--- a/net/sched/sch_gred.c
+++ b/net/sched/sch_gred.c
@@ -512,7 +512,7 @@ static int gred_dump(struct Qdisc *sch, struct sk_buff *skb)
opt=kmalloc(sizeof(struct tc_gred_qopt)*MAX_DPs, GFP_KERNEL);
if (opt == NULL) {
- DPRINTK("gred_dump:failed to malloc for %d\n",
+ DPRINTK("gred_dump:failed to malloc for %Zd\n",
sizeof(struct tc_gred_qopt)*MAX_DPs);
goto rtattr_failure;
}
diff --git a/net/socket.c b/net/socket.c
index fb5158241..309f76bc4 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -130,7 +130,7 @@ static struct file_operations socket_file_ops = {
static struct net_proto_family *net_families[NPROTO];
-#ifdef __SMP__
+#ifdef CONFIG_SMP
static atomic_t net_family_lockct = ATOMIC_INIT(0);
static spinlock_t net_family_lock = SPIN_LOCK_UNLOCKED;
@@ -561,21 +561,16 @@ int sock_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
}
+/* No kernel lock held - perfect */
static unsigned int sock_poll(struct file *file, poll_table * wait)
{
struct socket *sock;
- int err;
-
- unlock_kernel();
- sock = socki_lookup(file->f_dentry->d_inode);
/*
* We can't return errors to poll, so it's either yes or no.
*/
-
- err = sock->ops->poll(file, sock, wait);
- lock_kernel();
- return err;
+ sock = socki_lookup(file->f_dentry->d_inode);
+ return sock->ops->poll(file, sock, wait);
}
static int sock_mmap(struct file * file, struct vm_area_struct * vma)
@@ -1397,7 +1392,7 @@ int sock_fcntl(struct file *filp, unsigned int cmd, unsigned long arg)
sock = socki_lookup (filp->f_dentry->d_inode);
if (sock && sock->ops)
- return sock->ops->fcntl(sock, cmd, arg);
+ return sock_no_fcntl(sock, cmd, arg);
return(-EINVAL);
}
@@ -1618,7 +1613,7 @@ int socket_get_info(char *buffer, char **start, off_t offset, int length)
int counter = 0;
for (cpu=0; cpu<smp_num_cpus; cpu++)
- counter += sockets_in_use[cpu].counter;
+ counter += sockets_in_use[cpu_logical_map(cpu)].counter;
/* It can be negative, by the way. 8) */
if (counter < 0)
diff --git a/net/sunrpc/Makefile b/net/sunrpc/Makefile
index 1bf4f6070..ef5030354 100644
--- a/net/sunrpc/Makefile
+++ b/net/sunrpc/Makefile
@@ -11,13 +11,17 @@ O_TARGET := sunrpc.o
O_OBJS := clnt.o xprt.o sched.o \
auth.o auth_null.o auth_unix.o \
svc.o svcsock.o svcauth.o \
- pmap_clnt.o xdr.o sysctl.o
+ pmap_clnt.o xdr.o
OX_OBJS := sunrpc_syms.o
ifeq ($(CONFIG_PROC_FS),y)
O_OBJS += stats.o
endif
+ifeq ($(CONFIG_SYSCTL),y)
+ O_OBJS += sysctl.o
+endif
+
M_OBJS := $(O_TARGET)
include $(TOPDIR)/Rules.make
diff --git a/net/sunrpc/pmap_clnt.c b/net/sunrpc/pmap_clnt.c
index 6afb28e88..026edcd70 100644
--- a/net/sunrpc/pmap_clnt.c
+++ b/net/sunrpc/pmap_clnt.c
@@ -91,8 +91,8 @@ rpc_getport_external(struct sockaddr_in *sin, __u32 prog, __u32 vers, int prot)
char hostname[32];
int status;
- dprintk("RPC: rpc_getport_external(%s, %d, %d, %d)\n",
- in_ntoa(sin->sin_addr.s_addr), prog, vers, prot);
+ dprintk("RPC: rpc_getport_external(%u.%u.%u.%u, %d, %d, %d)\n",
+ NIPQUAD(sin->sin_addr.s_addr), prog, vers, prot);
strcpy(hostname, in_ntoa(sin->sin_addr.s_addr));
if (!(pmap_clnt = pmap_create(hostname, sin, prot)))
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index da46ab910..c4d946cb3 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -1015,7 +1015,7 @@ rpciod(void *ptr)
current->session = 1;
current->pgrp = 1;
- sprintf(current->comm, "rpciod");
+ strcpy(current->comm, "rpciod");
dprintk("RPC: rpciod starting (pid %d)\n", rpciod_pid);
while (rpciod_users) {
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c
index 36da3b619..e53759e3e 100644
--- a/net/sunrpc/sunrpc_syms.c
+++ b/net/sunrpc/sunrpc_syms.c
@@ -95,6 +95,7 @@ EXPORT_SYMBOL(xdr_decode_netobj);
EXPORT_SYMBOL(xdr_encode_netobj);
EXPORT_SYMBOL(xdr_zero);
EXPORT_SYMBOL(xdr_one);
+EXPORT_SYMBOL(xdr_two);
EXPORT_SYMBOL(xdr_shift_iovec);
EXPORT_SYMBOL(xdr_zero_iovec);
@@ -104,7 +105,9 @@ EXPORT_SYMBOL(rpc_garbage_args);
EXPORT_SYMBOL(rpc_system_err);
/* Debugging symbols */
+#ifdef RPC_DEBUG
EXPORT_SYMBOL(rpc_debug);
EXPORT_SYMBOL(nfs_debug);
EXPORT_SYMBOL(nfsd_debug);
EXPORT_SYMBOL(nlm_debug);
+#endif
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index d99033fa5..f64653120 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -544,14 +544,14 @@ svc_tcp_accept(struct svc_sock *svsk)
if (ntohs(sin.sin_port) >= 1024) {
if (net_ratelimit())
printk(KERN_WARNING
- "%s: connect from unprivileged port: %s:%d",
+ "%s: connect from unprivileged port: %u.%u.%u.%u:%d",
serv->sv_name,
- in_ntoa(sin.sin_addr.s_addr), ntohs(sin.sin_port));
+ NIPQUAD(sin.sin_addr.s_addr), ntohs(sin.sin_port));
goto failed;
}
- dprintk("%s: connect from %s:%04x\n", serv->sv_name,
- in_ntoa(sin.sin_addr.s_addr), ntohs(sin.sin_port));
+ dprintk("%s: connect from %u.%u.%u.%u:%04x\n", serv->sv_name,
+ NIPQUAD(sin.sin_addr.s_addr), ntohs(sin.sin_port));
if (!(newsvsk = svc_setup_socket(serv, newsock, &err, 0)))
goto failed;
@@ -915,9 +915,9 @@ svc_create_socket(struct svc_serv *serv, int protocol, struct sockaddr_in *sin)
int error;
int type;
- dprintk("svc: svc_create_socket(%s, %d, %08x:%d)\n",
+ dprintk("svc: svc_create_socket(%s, %d, %u.%u.%u.%u:%d)\n",
serv->sv_program->pg_name, protocol,
- ntohl(sin->sin_addr.s_addr),
+ NIPQUAD(sin->sin_addr.s_addr),
ntohs(sin->sin_port));
if (protocol != IPPROTO_UDP && protocol != IPPROTO_TCP) {
diff --git a/net/sunrpc/sysctl.c b/net/sunrpc/sysctl.c
index 6219c3720..be49a16a1 100644
--- a/net/sunrpc/sysctl.c
+++ b/net/sunrpc/sysctl.c
@@ -57,7 +57,7 @@ rpc_unregister_sysctl(void)
}
}
-int
+static int
proc_dodebug(ctl_table *table, int write, struct file *file,
void *buffer, size_t *lenp)
{
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 12a4b1eb3..15a3a6abc 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -8,7 +8,7 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
- * Version: $Id: af_unix.c,v 1.91 2000/03/25 01:55:34 davem Exp $
+ * Version: $Id: af_unix.c,v 1.94 2000/04/25 04:13:35 davem Exp $
*
* Fixes:
* Linus Torvalds : Assorted bug cures.
@@ -1103,6 +1103,9 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg, int len,
(err = unix_autobind(sock)) != 0)
goto out;
+ err = -EMSGSIZE;
+ if ((unsigned)len > sk->sndbuf - 32)
+ goto out;
skb = sock_alloc_send_skb(sk, len, 0, msg->msg_flags&MSG_DONTWAIT, &err);
if (skb==NULL)
@@ -1719,45 +1722,43 @@ done:
#endif
struct proto_ops unix_stream_ops = {
- PF_UNIX,
+ family: PF_UNIX,
- unix_release,
- unix_bind,
- unix_stream_connect,
- unix_socketpair,
- unix_accept,
- unix_getname,
- unix_poll,
- unix_ioctl,
- unix_listen,
- unix_shutdown,
- sock_no_setsockopt,
- sock_no_getsockopt,
- sock_no_fcntl,
- unix_stream_sendmsg,
- unix_stream_recvmsg,
- sock_no_mmap
+ release: unix_release,
+ bind: unix_bind,
+ connect: unix_stream_connect,
+ socketpair: unix_socketpair,
+ accept: unix_accept,
+ getname: unix_getname,
+ poll: unix_poll,
+ ioctl: unix_ioctl,
+ listen: unix_listen,
+ shutdown: unix_shutdown,
+ setsockopt: sock_no_setsockopt,
+ getsockopt: sock_no_getsockopt,
+ sendmsg: unix_stream_sendmsg,
+ recvmsg: unix_stream_recvmsg,
+ mmap: sock_no_mmap,
};
struct proto_ops unix_dgram_ops = {
- PF_UNIX,
+ family: PF_UNIX,
- unix_release,
- unix_bind,
- unix_dgram_connect,
- unix_socketpair,
- sock_no_accept,
- unix_getname,
- datagram_poll,
- unix_ioctl,
- sock_no_listen,
- unix_shutdown,
- sock_no_setsockopt,
- sock_no_getsockopt,
- sock_no_fcntl,
- unix_dgram_sendmsg,
- unix_dgram_recvmsg,
- sock_no_mmap
+ release: unix_release,
+ bind: unix_bind,
+ connect: unix_dgram_connect,
+ socketpair: unix_socketpair,
+ accept: sock_no_accept,
+ getname: unix_getname,
+ poll: datagram_poll,
+ ioctl: unix_ioctl,
+ listen: sock_no_listen,
+ shutdown: unix_shutdown,
+ setsockopt: sock_no_setsockopt,
+ getsockopt: sock_no_getsockopt,
+ sendmsg: unix_dgram_sendmsg,
+ recvmsg: unix_dgram_recvmsg,
+ mmap: sock_no_mmap,
};
struct net_proto_family unix_family_ops = {
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c
index e042ce1d8..ebaaa7242 100644
--- a/net/x25/af_x25.c
+++ b/net/x25/af_x25.c
@@ -17,6 +17,9 @@
* X.25 002 Jonathan Naylor Centralised disconnect handling.
* New timer architecture.
* 2000-11-03 Henner Eisen MSG_EOR handling more POSIX compliant.
+ * 2000-22-03 Daniela Squassoni Allowed disabling/enabling of
+ * facilities negotiation and increased
+ * the throughput upper limit.
*/
#include <linux/config.h>
@@ -811,6 +814,7 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *neigh, unsigned i
make->protinfo.x25->source_addr = source_addr;
make->protinfo.x25->neighbour = neigh;
make->protinfo.x25->facilities = facilities;
+ make->protinfo.x25->vc_facil_mask = sk->protinfo.x25->vc_facil_mask;
x25_write_internal(make, X25_CALL_ACCEPTED);
@@ -1133,7 +1137,7 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
return -EINVAL;
if (facilities.winsize_in < 1 || facilities.winsize_in > 127)
return -EINVAL;
- if (facilities.throughput < 0x03 || facilities.throughput > 0x2C)
+ if (facilities.throughput < 0x03 || facilities.throughput > 0xDD)
return -EINVAL;
if (facilities.reverse != 0 && facilities.reverse != 1)
return -EINVAL;
@@ -1239,24 +1243,23 @@ struct net_proto_family x25_family_ops = {
};
static struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = {
- AF_X25,
-
- x25_release,
- x25_bind,
- x25_connect,
- sock_no_socketpair,
- x25_accept,
- x25_getname,
- datagram_poll,
- x25_ioctl,
- x25_listen,
- sock_no_shutdown,
- x25_setsockopt,
- x25_getsockopt,
- sock_no_fcntl,
- x25_sendmsg,
- x25_recvmsg,
- sock_no_mmap
+ family: AF_X25,
+
+ release: x25_release,
+ bind: x25_bind,
+ connect: x25_connect,
+ socketpair: sock_no_socketpair,
+ accept: x25_accept,
+ getname: x25_getname,
+ poll: datagram_poll,
+ ioctl: x25_ioctl,
+ listen: x25_listen,
+ shutdown: sock_no_shutdown,
+ setsockopt: x25_setsockopt,
+ getsockopt: x25_getsockopt,
+ sendmsg: x25_sendmsg,
+ recvmsg: x25_recvmsg,
+ mmap: sock_no_mmap,
};
#include <linux/smp_lock.h>
diff --git a/net/x25/x25_facilities.c b/net/x25/x25_facilities.c
index 18de2da1a..ad41d1cde 100644
--- a/net/x25/x25_facilities.c
+++ b/net/x25/x25_facilities.c
@@ -14,6 +14,8 @@
*
* History
* X.25 001 Split from x25_subr.c
+ * mar/20/00 Daniela Squassoni Disabling/enabling of facilities
+ * negotiation.
*/
#include <linux/config.h>
@@ -43,12 +45,13 @@
* Parse a set of facilities into the facilities structure. Unrecognised
* facilities are written to the debug log file.
*/
-int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities)
+int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities, unsigned long *vc_fac_mask)
{
unsigned int len;
unsigned char *p = skb->data;
len = *p++;
+ *vc_fac_mask = 0;
while (len > 0) {
switch (*p & X25_FAC_CLASS_MASK) {
@@ -56,9 +59,11 @@ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities)
switch (*p) {
case X25_FAC_REVERSE:
facilities->reverse = (p[1] & 0x01);
+ *vc_fac_mask |= X25_MASK_REVERSE;
break;
case X25_FAC_THROUGHPUT:
facilities->throughput = p[1];
+ *vc_fac_mask |= X25_MASK_THROUGHPUT;
break;
default:
printk(KERN_DEBUG "X.25: unknown facility %02X, value %02X\n", p[0], p[1]);
@@ -73,10 +78,12 @@ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities)
case X25_FAC_PACKET_SIZE:
facilities->pacsize_in = p[1];
facilities->pacsize_out = p[2];
+ *vc_fac_mask |= X25_MASK_PACKET_SIZE;
break;
case X25_FAC_WINDOW_SIZE:
facilities->winsize_in = p[1];
facilities->winsize_out = p[2];
+ *vc_fac_mask |= X25_MASK_WINDOW_SIZE;
break;
default:
printk(KERN_DEBUG "X.25: unknown facility %02X, values %02X, %02X\n", p[0], p[1], p[2]);
@@ -106,28 +113,34 @@ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities)
/*
* Create a set of facilities.
*/
-int x25_create_facilities(unsigned char *buffer, struct x25_facilities *facilities)
+int x25_create_facilities(unsigned char *buffer, struct x25_facilities *facilities, unsigned long facil_mask)
{
unsigned char *p = buffer + 1;
int len;
- if (facilities->reverse != 0) {
+ if (facil_mask == 0) {
+ buffer [0] = 0; /* length of the facilities field in call_req or call_accept packets */
+ len = 1; /* 1 byte for the length field */
+ return len;
+ }
+
+ if ((facilities->reverse != 0) && (facil_mask & X25_MASK_REVERSE)) {
*p++ = X25_FAC_REVERSE;
*p++ = (facilities->reverse) ? 0x01 : 0x00;
}
- if (facilities->throughput != 0) {
+ if ((facilities->throughput != 0) && (facil_mask & X25_MASK_THROUGHPUT)) {
*p++ = X25_FAC_THROUGHPUT;
*p++ = facilities->throughput;
}
- if (facilities->pacsize_in != 0 || facilities->pacsize_out != 0) {
+ if ((facilities->pacsize_in != 0 || facilities->pacsize_out != 0) && (facil_mask & X25_MASK_PACKET_SIZE)) {
*p++ = X25_FAC_PACKET_SIZE;
*p++ = (facilities->pacsize_in == 0) ? facilities->pacsize_out : facilities->pacsize_in;
*p++ = (facilities->pacsize_out == 0) ? facilities->pacsize_in : facilities->pacsize_out;
}
- if (facilities->winsize_in != 0 || facilities->winsize_out != 0) {
+ if ((facilities->winsize_in != 0 || facilities->winsize_out != 0) && (facil_mask & X25_MASK_WINDOW_SIZE)) {
*p++ = X25_FAC_WINDOW_SIZE;
*p++ = (facilities->winsize_in == 0) ? facilities->winsize_out : facilities->winsize_in;
*p++ = (facilities->winsize_out == 0) ? facilities->winsize_in : facilities->winsize_out;
@@ -156,7 +169,7 @@ int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk, struct x25_fa
*new = *ours;
- len = x25_parse_facilities(skb, &theirs);
+ len = x25_parse_facilities(skb, &theirs, &sk->protinfo.x25->vc_facil_mask);
/*
* They want reverse charging, we won't accept it.
diff --git a/net/x25/x25_in.c b/net/x25/x25_in.c
index a8a2905fe..5110d327a 100644
--- a/net/x25/x25_in.c
+++ b/net/x25/x25_in.c
@@ -13,9 +13,11 @@
* 2 of the License, or (at your option) any later version.
*
* History
- * X.25 001 Jonathan Naylor Started coding.
- * X.25 002 Jonathan Naylor Centralised disconnection code.
- * New timer architecture.
+ * X.25 001 Jonathan Naylor Started coding.
+ * X.25 002 Jonathan Naylor Centralised disconnection code.
+ * New timer architecture.
+ * mar/20/00 Daniela Squassoni Disabling/enabling of facilities
+ * negotiation.
*/
#include <linux/config.h>
@@ -111,7 +113,7 @@ static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametyp
*/
skb_pull(skb, X25_STD_MIN_LEN);
skb_pull(skb, x25_addr_ntoa(skb->data, &source_addr, &dest_addr));
- skb_pull(skb, x25_parse_facilities(skb, &sk->protinfo.x25->facilities));
+ skb_pull(skb, x25_parse_facilities(skb, &sk->protinfo.x25->facilities, &sk->protinfo.x25->vc_facil_mask));
/*
* Copy any Call User Data.
*/
diff --git a/net/x25/x25_link.c b/net/x25/x25_link.c
index d33dc63c3..34d065b83 100644
--- a/net/x25/x25_link.c
+++ b/net/x25/x25_link.c
@@ -13,8 +13,10 @@
* 2 of the License, or (at your option) any later version.
*
* History
- * X.25 001 Jonathan Naylor Started coding.
- * X.25 002 Jonathan Naylor New timer architecture.
+ * X.25 001 Jonathan Naylor Started coding.
+ * X.25 002 Jonathan Naylor New timer architecture.
+ * mar/20/00 Daniela Squassoni Disabling/enabling of facilities
+ * negotiation.
*/
#include <linux/config.h>
@@ -293,6 +295,7 @@ void x25_link_device_up(struct net_device *dev)
x25_neigh->dev = dev;
x25_neigh->state = X25_LINK_STATE_0;
x25_neigh->extended = 0;
+ x25_neigh->global_facil_mask = (X25_MASK_REVERSE | X25_MASK_THROUGHPUT | X25_MASK_PACKET_SIZE | X25_MASK_WINDOW_SIZE); /* enables negotiation */
x25_neigh->t20 = sysctl_x25_restart_request_timeout;
save_flags(flags); cli();
@@ -377,6 +380,8 @@ int x25_subscr_ioctl(unsigned int cmd, void *arg)
switch (cmd) {
case SIOCX25GSUBSCRIP:
+ if (copy_from_user(&x25_subscr, arg, sizeof(struct x25_subscrip_struct)))
+ return -EFAULT;
if ((dev = x25_dev_get(x25_subscr.device)) == NULL)
return -EINVAL;
if ((x25_neigh = x25_get_neigh(dev)) == NULL) {
@@ -385,6 +390,7 @@ int x25_subscr_ioctl(unsigned int cmd, void *arg)
}
dev_put(dev);
x25_subscr.extended = x25_neigh->extended;
+ x25_subscr.global_facil_mask = x25_neigh->global_facil_mask;
if (copy_to_user(arg, &x25_subscr, sizeof(struct x25_subscrip_struct)))
return -EFAULT;
break;
@@ -402,6 +408,7 @@ int x25_subscr_ioctl(unsigned int cmd, void *arg)
if (x25_subscr.extended != 0 && x25_subscr.extended != 1)
return -EINVAL;
x25_neigh->extended = x25_subscr.extended;
+ x25_neigh->global_facil_mask = x25_subscr.global_facil_mask;
break;
default:
diff --git a/net/x25/x25_subr.c b/net/x25/x25_subr.c
index 8b055e40e..25a700af9 100644
--- a/net/x25/x25_subr.c
+++ b/net/x25/x25_subr.c
@@ -13,8 +13,10 @@
* 2 of the License, or (at your option) any later version.
*
* History
- * X.25 001 Jonathan Naylor Started coding.
- * X.25 002 Jonathan Naylor Centralised disconnection processing.
+ * X.25 001 Jonathan Naylor Started coding.
+ * X.25 002 Jonathan Naylor Centralised disconnection processing.
+ * mar/20/00 Daniela Squassoni Disabling/enabling of facilities
+ * negotiation.
*/
#include <linux/config.h>
@@ -206,7 +208,7 @@ void x25_write_internal(struct sock *sk, int frametype)
len = x25_addr_aton(addresses, &sk->protinfo.x25->dest_addr, &sk->protinfo.x25->source_addr);
dptr = skb_put(skb, len);
memcpy(dptr, addresses, len);
- len = x25_create_facilities(facilities, &sk->protinfo.x25->facilities);
+ len = x25_create_facilities(facilities, &sk->protinfo.x25->facilities, sk->protinfo.x25->neighbour->global_facil_mask);
dptr = skb_put(skb, len);
memcpy(dptr, facilities, len);
dptr = skb_put(skb, sk->protinfo.x25->calluserdata.cudlength);
@@ -218,7 +220,7 @@ void x25_write_internal(struct sock *sk, int frametype)
dptr = skb_put(skb, 2);
*dptr++ = X25_CALL_ACCEPTED;
*dptr++ = 0x00; /* Address lengths */
- len = x25_create_facilities(facilities, &sk->protinfo.x25->facilities);
+ len = x25_create_facilities(facilities, &sk->protinfo.x25->facilities, sk->protinfo.x25->vc_facil_mask);
dptr = skb_put(skb, len);
memcpy(dptr, facilities, len);
dptr = skb_put(skb, sk->protinfo.x25->calluserdata.cudlength);