From 5a5d5deebd1eb93a84048cc0103fe4c27d2215e1 Mon Sep 17 00:00:00 2001 From: Michael Blizek Date: Sat, 25 Sep 2021 09:23:40 +0200 Subject: [PATCH] add config.c, neigh_ann_rcv.c, neigh_ann_snd.c --- net/cor/Makefile | 4 +- net/cor/common.c | 8 +- net/cor/config.c | 186 +++++++++++++ net/cor/cor.h | 104 +++++-- net/cor/neigh_ann_rcv.c | 340 +++++++++++++++++++++++ net/cor/neigh_ann_snd.c | 275 +++++++++++++++++++ net/cor/neighbor.c | 701 +----------------------------------------------- net/cor/sock_rdaemon.c | 100 +------ 8 files changed, 900 insertions(+), 818 deletions(-) create mode 100644 net/cor/config.c create mode 100644 net/cor/neigh_ann_rcv.c create mode 100644 net/cor/neigh_ann_snd.c diff --git a/net/cor/Makefile b/net/cor/Makefile index 91b71b8e183d..076de193efa4 100644 --- a/net/cor/Makefile +++ b/net/cor/Makefile @@ -1 +1,3 @@ -obj-y := dev.o common.o util.o credits.o rcv.o snd.o sock_rdaemon.o sock_raw.o sock_managed.o sock.o kpacket_parse.o kpacket_gen.o cpacket_parse.o neighbor.o forward.o +obj-y := config.o dev.o util.o sock_rdaemon.o sock_raw.o sock_managed.o sock.o \ + forward.o common.o credits.o rcv.o snd.o cpacket_parse.o \ + neighbor.o neigh_ann_snd.o neigh_ann_rcv.o kpacket_gen.o kpacket_parse.o diff --git a/net/cor/common.c b/net/cor/common.c index 3abd6e91022f..da70ded83761 100644 --- a/net/cor/common.c +++ b/net/cor/common.c @@ -1035,6 +1035,10 @@ static int __init cor_init(void) if (unlikely(rc != 0)) return rc; + rc = cor_neigh_ann_rcv_init(); + if (unlikely(rc != 0)) + return rc; + rc = cor_dev_init(); if (unlikely(rc != 0)) return rc; @@ -1064,10 +1068,12 @@ static void __exit cor_exit(void) cor_sock_exit1(); cor_sock_managed_exit1(); cor_dev_exit1(); - cor_neighbor_exit1(); + + flush_scheduled_work(); cor_rcv_exit2(); cor_neighbor_exit2(); + cor_neigh_ann_rcv_exit2(); cor_snd_exit2(); cor_rd_exit2(); cor_kgen_exit2(); diff --git a/net/cor/config.c b/net/cor/config.c new file mode 100644 index 000000000000..ef9699d40034 --- /dev/null +++ b/net/cor/config.c @@ -0,0 +1,186 @@ +/** + * Connection oriented routing + * Copyright (C) 2007-2021 Michael Blizek + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include "cor.h" + +static DEFINE_MUTEX(cor_config_lock); + +DEFINE_SPINLOCK(cor_local_addr_lock); +char *cor_local_addr; +__u32 cor_local_addrlen; +__be32 cor_local_addr_sessionid; + + +static DEFINE_SPINLOCK(cor_interface_config_lock); +static struct cor_interface_config *cor_interface_config = 0; +static __u32 cor_num_interfaces = 0; +static int cor_all_interfaces = 0; + + +int cor_is_device_configurated(struct net_device *dev) +{ + int ret = 0; + + unsigned long iflags; + + __u32 i; + spin_lock_irqsave(&cor_interface_config_lock, iflags); + + if (cor_all_interfaces != 0) { + ret = 1; + goto out; + } + + BUG_ON(cor_num_interfaces > 65536); + for (i=0;iname == 0); + + for (j=0;;j++) { + if (j >= sizeof(dev->name)) + break; + + if (dev->name[j] == 0 && j == curr->name_len) { + ret = 1; + goto out; + } + + if (dev->name[j] == 0 || j >= curr->name_len) + break; + + if (dev->name[j] != curr->name[j]) + break; + } + } + +out: + spin_unlock_irqrestore(&cor_interface_config_lock, iflags); + + return ret; +} + +void cor_set_interface_config(struct cor_interface_config *new_config, + __u32 new_num_interfaces, int new_all_interfaces) +{ + unsigned long iflags; + __u32 i; + + spin_lock_irqsave(&cor_interface_config_lock, iflags); + + BUG_ON(cor_num_interfaces > 65536); + for (i=0;iname == 0); + kfree(curr->name); + curr->name = 0; + } + + kfree(cor_interface_config); + cor_interface_config = 0; + cor_num_interfaces = 0; + cor_all_interfaces = 0; + + + cor_interface_config = new_config; + cor_num_interfaces = new_num_interfaces; + cor_all_interfaces = new_all_interfaces; + + spin_unlock_irqrestore(&cor_interface_config_lock, iflags); +} + + +void _cor_config_down(void) +{ + cor_dev_down(); + + spin_lock_bh(&cor_local_addr_lock); + if (cor_local_addr != 0) { + kfree(cor_local_addr); + cor_local_addr = 0; + } + cor_local_addrlen = 0; + spin_unlock_bh(&cor_local_addr_lock); + + cor_reset_neighbors(0); + cor_reset_neighbors(0); + cor_destroy_queue(0); + + cor_announce_send_stop(0, 0, ANNOUNCE_TYPE_BROADCAST); +} + +void cor_config_down(void) +{ + mutex_lock(&(cor_config_lock)); + _cor_config_down(); + mutex_unlock(&(cor_config_lock)); +} + +int cor_config_up(char *addr2, __u32 addrlen2) +{ + int rc = 0; + + char *addr2_copy = kmalloc(addrlen2, GFP_KERNEL); + if (unlikely(addr2_copy == 0)) + return 1; + + memcpy(addr2_copy, addr2, addrlen2); + + mutex_lock(&(cor_config_lock)); + + _cor_config_down(); + + spin_lock_bh(&cor_local_addr_lock); + + BUG_ON(cor_local_addr != 0); + BUG_ON(cor_local_addrlen != 0); + + cor_local_addr = addr2_copy; + addr2_copy = 0; + cor_local_addrlen = addrlen2; + get_random_bytes((char *) &cor_local_addr_sessionid, + sizeof(cor_local_addr_sessionid)); + + spin_unlock_bh(&cor_local_addr_lock); + + if (cor_dev_up() != 0) { + spin_lock_bh(&cor_local_addr_lock); + kfree(cor_local_addr); + cor_local_addr = 0; + cor_local_addrlen = 0; + spin_unlock_bh(&cor_local_addr_lock); + rc = 1; + } + + mutex_unlock(&(cor_config_lock)); + + return rc; +} + +int cor_is_clientmode(void) +{ + int rc; + spin_lock_bh(&cor_local_addr_lock); + rc = (cor_local_addrlen == 0 ? 1 : 0); + spin_unlock_bh(&cor_local_addr_lock); + return rc; +} diff --git a/net/cor/cor.h b/net/cor/cor.h index 8e4d968cabb3..2d0879c89f4b 100644 --- a/net/cor/cor.h +++ b/net/cor/cor.h @@ -75,6 +75,29 @@ struct cor_sockaddr { #define PACKET_TYPE_CONNDATA_FLUSH 6 #define PACKET_TYPE_CONNDATA_LOWBUFDELAYED_FLUSH 7 + +/** + * Announce data format: + * version [2] + * is 0, may be increased if the protocol changes + * min_version [2] + * is 0, must be increased if a future version of the protocol is incompatible + * to the current version + * [data] + * + * Data format of the announce packet "data" field: + *{command [2] commandlength [2] commanddata [commandlength]}[...] + */ + +/* Commands */ + +/* ANNCMD_VERSION: version[2] minversion[2] */ +#define ANNCMD_VERSION 1 + +/* ANNCMD_ADDR: addrlen[2] addr[addrlen] */ +#define ANNCMD_ADDR 2 + + /* * Kernel packet data - these commands are sent by the neighbor * The end nodes may cause these commands to be sent, but they see them beyond @@ -373,16 +396,10 @@ static inline int cor_ack_conn_len(__u8 flags) #define PRIORITY_MAX 15384774 - - -/* result codes for rcv.c/proc_packet */ -#define RC_DROP 0 -#define RC_FINISHED 1 - -#define RC_RCV1_ANNOUNCE 2 -#define RC_RCV1_KERNEL 3 -#define RC_RCV1_CONN 4 - +struct cor_interface_config { + char *name; + __u32 name_len; +}; #define CONGSTATUS_NONE 0 #define CONGSTATUS_CONNDATA 1 @@ -451,6 +468,27 @@ struct cor_announce_data{ struct cor_resume_block rb; }; +struct cor_neighbor_discdata{ + struct list_head lh; + unsigned long jiffies_created; + + __be32 sessionid; + + struct net_device *dev; + char mac[MAX_ADDR_LEN]; + + __u8 nb_allocated; + + __u8 rcvd_version; + __u8 rcvd_addr; + + __u16 version; + __u16 minversion; + + char *addr; + __u16 addrlen; +}; + struct cor_ping_cookie{ ktime_t time_created; ktime_t time_sent; @@ -1079,9 +1117,24 @@ struct cor_sock { atomic_t ready_to_accept; }; +/* config.c */ +extern spinlock_t cor_local_addr_lock; +extern char *cor_local_addr; +extern __u32 cor_local_addrlen; +extern __be32 cor_local_addr_sessionid; -/* dev.c */ +extern int cor_is_device_configurated(struct net_device *dev); + +extern void cor_set_interface_config(struct cor_interface_config *new_config, + __u32 new_num_interfaces, int new_all_interfaces); + +extern void cor_config_down(void); + +extern int cor_config_up(char *addr2, __u32 addrlen2); + +extern int cor_is_clientmode(void); +/* dev.c */ extern void cor_qos_set_lastdrop(struct cor_qos_queue *q); #ifdef DEBUG_QOS_SLOWSEND @@ -1261,10 +1314,15 @@ extern void cor_set_conn_in_priority(struct cor_neighbor *nb, __u32 conn_id, extern void cor_connreset_priority(struct cor_conn *cn); /* neighbor.c */ +extern atomic_t cor_num_neighs; + extern void cor_neighbor_free(struct kref *ref); extern int cor_is_from_nb(struct sk_buff *skb, struct cor_neighbor *nb); +extern struct cor_neighbor *_cor_get_neigh_by_mac(struct net_device *dev, + char *source_hw); + extern struct cor_neighbor *cor_get_neigh_by_mac(struct sk_buff *skb); extern struct cor_neighbor *cor_find_neigh(char *addr, __u16 addrlen); @@ -1293,8 +1351,20 @@ extern int cor_time_to_send_ping(struct cor_neighbor *nb); extern unsigned long cor_get_next_ping_time(struct cor_neighbor *nb); +extern void cor_add_neighbor(struct cor_neighbor_discdata *nb_dd); + +extern int __init cor_neighbor_init(void); + +extern void __exit cor_neighbor_exit2(void); + +/* neigh_ann_rcv.c */ extern int cor_rcv_announce(struct sk_buff *skb); +extern int __init cor_neigh_ann_rcv_init(void); + +extern void __exit cor_neigh_ann_rcv_exit2(void); + +/* neigh_ann_snd.c */ extern int _cor_send_announce(struct cor_announce_data *ann, int fromqos, int *sent); @@ -1305,18 +1375,6 @@ extern void cor_announce_send_start(struct net_device *dev, char *mac, extern void cor_announce_send_stop(struct net_device *dev, char *mac, int type); -extern void cor_neighbor_down(void); - -extern int cor_neighbor_up(char *addr2, __u32 addrlen2); - -extern int cor_is_clientmode(void); - -extern int __init cor_neighbor_init(void); - -extern void __exit cor_neighbor_exit1(void); - -extern void __exit cor_neighbor_exit2(void); - /* rcv.c */ extern void cor_reset_ooo_queue(struct cor_conn *src_in_lx); diff --git a/net/cor/neigh_ann_rcv.c b/net/cor/neigh_ann_rcv.c new file mode 100644 index 000000000000..e9168baa2104 --- /dev/null +++ b/net/cor/neigh_ann_rcv.c @@ -0,0 +1,340 @@ +/** + * Connection oriented routing + * Copyright (C) 2007-2021 Michael Blizek + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include "cor.h" + +static atomic_t cor_packets_in_workqueue = ATOMIC_INIT(0); + +static DEFINE_MUTEX(cor_announce_rcv_lock); +static LIST_HEAD(cor_nb_dd_list); /* protected by cor_announce_rcv_lock */ +static __u32 cor_num_nb_dd = 0; +static struct kmem_cache *cor_nb_dd_slab; + +static int cor_parse_announce_version(struct cor_neighbor_discdata *nb_dd, + __u16 cmd, char *cmddata, __u16 len) +{ + __u16 version; + __u16 minversion; + + if (unlikely(len < 4)) + return 1; + + version = cor_parse_u16(cmddata); + cmddata += 2; + len -= 2; + minversion = cor_parse_u16(cmddata); + cmddata += 2; + len -= 2; + + if (minversion != 0) + return 1; + + if (nb_dd->rcvd_version != 0) { + if (nb_dd->version != version || + nb_dd->minversion != minversion) + return 1; + } else { + nb_dd->version = version; + nb_dd->minversion = minversion; + nb_dd->rcvd_version = 1; + } + + return 0; +} + +static int cor_parse_announce_addaddr(struct cor_neighbor_discdata *nb_dd, + __u16 cmd, char *cmddata, __u16 len) +{ + __u16 addrlen; + char *addr; + + BUG_ON(cmd != ANNCMD_ADDR); + BUG_ON((nb_dd->addr == 0) != (nb_dd->addrlen == 0)); + BUG_ON(nb_dd->rcvd_addr == 0 && nb_dd->addr != 0); + + if (len < 2) + return 1; + + addrlen = cor_parse_u16(cmddata); + cmddata += 2; + len -= 2; + + if (len < addrlen) + return 1; + + addr = cmddata; + cmddata += addrlen; + len -= addrlen; + + if (nb_dd->rcvd_addr != 0) { + if (nb_dd->addrlen != addrlen) + return 1; + if (addrlen != 0 && memcmp(nb_dd->addr, addr, addrlen) != 0) + return 1; + } else { + if (addrlen != 0) { + nb_dd->addr = kmalloc(addrlen, GFP_KERNEL); + if (unlikely(nb_dd->addr == 0)) + return 1; + + memcpy(nb_dd->addr, addr, addrlen); + } + nb_dd->addrlen = addrlen; + + nb_dd->rcvd_addr = 1; + } + + return 0; +} + +static int cor_parse_announce_cmd(struct cor_neighbor_discdata *nb_dd, + __u16 cmd, char *cmddata, __u16 len) +{ + if (cmd == ANNCMD_VERSION) { + return cor_parse_announce_version(nb_dd, cmd, cmddata, len); + } else if (cmd == ANNCMD_ADDR) { + return cor_parse_announce_addaddr(nb_dd, cmd, cmddata, len); + } else { + return 1; + } +} + +static int cor_parse_announce_cmds(struct cor_neighbor_discdata *nb_dd, + char *msg, __u32 len) +{ + __u32 zeros = 0; + while (zeros < len) { + if (msg[len-zeros-1] != 0) + break; + zeros++; + } + + while (len >= 4 && len > zeros) { + __u16 cmd; + __u16 cmdlen; + + cmd = cor_parse_u16(msg); + msg += 2; + len -= 2; + cmdlen = cor_parse_u16(msg); + msg += 2; + len -= 2; + + if (cmdlen > len) + return 1; + + if (cor_parse_announce_cmd(nb_dd, cmd, msg, cmdlen) != 0) + return 1; + + msg += cmdlen; + len -= cmdlen; + } + + if (len != 0 && len < zeros) + return 1; + + return 0; +} + +static void cor_neighbor_discdata_free(struct cor_neighbor_discdata *nb_dd) +{ + list_del(&(nb_dd->lh)); + + BUG_ON(nb_dd->dev == 0); + dev_put(nb_dd->dev); + + if (nb_dd->addr != 0) { + kfree(nb_dd->addr); + nb_dd->addr = 0; + nb_dd->addrlen = 0; + } + + kmem_cache_free(cor_nb_dd_slab, nb_dd); + + BUG_ON(cor_num_nb_dd == 0); + cor_num_nb_dd--; +} + +static struct cor_neighbor_discdata *cor_findoralloc_neighbor_discdata( + struct net_device *dev, char *source_hw, __be32 sessionid) +{ + unsigned long jiffies_tmp = jiffies; + struct list_head *currlh; + + __u32 neighs; + struct cor_neighbor_discdata *nb_dd; + + currlh = cor_nb_dd_list.next; + while (currlh != &cor_nb_dd_list) { + struct cor_neighbor_discdata *curr = container_of(currlh, + struct cor_neighbor_discdata, lh); + + currlh = currlh->next; + + if (time_after(jiffies_tmp, curr->jiffies_created + + HZ * NEIGHBOR_DISCOVERY_TIMEOUT_SEC)) { + cor_neighbor_discdata_free(curr); + continue; + } + + if (curr->sessionid == sessionid && curr->dev == dev && + memcmp(curr->mac, source_hw, MAX_ADDR_LEN) == 0) + return curr; + } + + neighs = atomic_read(&cor_num_neighs); + if (neighs + cor_num_nb_dd < neighs || + neighs + cor_num_nb_dd >= MAX_NEIGHBORS) + return 0; + cor_num_nb_dd++; + + nb_dd = kmem_cache_alloc(cor_nb_dd_slab, GFP_KERNEL); + if (unlikely(nb_dd == 0)) + return 0; + + memset(nb_dd, 0, sizeof(struct cor_neighbor_discdata)); + + nb_dd->sessionid = sessionid; + + dev_hold(dev); + nb_dd->dev = dev; + + memcpy(nb_dd->mac, source_hw, MAX_ADDR_LEN); + + list_add_tail(&(nb_dd->lh), &cor_nb_dd_list); + nb_dd->jiffies_created = jiffies_tmp; + + if (cor_is_clientmode()) + cor_announce_send_start(dev, source_hw, ANNOUNCE_TYPE_UNICAST); + + return nb_dd; +} + +static void cor_parse_announce(struct net_device *dev, char *source_hw, + char *msg, __u32 len) +{ + __be32 sessionid; + struct cor_neighbor_discdata *nb_dd; + + + if (unlikely(len < 4)) + return; + + sessionid = cor_parse_be32(msg); + msg += 4; + len -= 4; + + nb_dd = cor_findoralloc_neighbor_discdata(dev, source_hw, sessionid); + if (unlikely(nb_dd == 0)) + return; + + if (cor_parse_announce_cmds(nb_dd, msg, len) != 0) + goto error; + + if (nb_dd->rcvd_version != 0 && nb_dd->rcvd_addr != 0) { + cor_add_neighbor(nb_dd); + +error: + cor_neighbor_discdata_free(nb_dd); + } +} + +static void _cor_rcv_announce(struct work_struct *work) +{ + struct cor_skb_procstate *ps = container_of(work, + struct cor_skb_procstate, funcstate.announce1.work); + struct sk_buff *skb = cor_skb_from_pstate(ps); + + char source_hw[MAX_ADDR_LEN]; + + struct cor_neighbor *nb; + + char *msg; + __u16 len; + + if (cor_is_device_configurated(skb->dev) == 0) + goto discard; + + memset(source_hw, 0, MAX_ADDR_LEN); + if (skb->dev->header_ops != 0 && + skb->dev->header_ops->parse != 0) + skb->dev->header_ops->parse(skb, source_hw); + + nb = _cor_get_neigh_by_mac(skb->dev, source_hw); + if (nb != 0) { + kref_put(&(nb->ref), cor_neighbor_free); + nb = 0; + goto discard; + } + + if (unlikely(skb->len > 65535 || skb->len < 0)) + goto discard; + len = (__u16) skb->len; + + msg = cor_pull_skb(skb, len); + if (msg == 0) + goto discard; + + mutex_lock(&(cor_announce_rcv_lock)); + cor_parse_announce(skb->dev, source_hw, msg, len); + mutex_unlock(&(cor_announce_rcv_lock)); + +discard: + kfree_skb(skb); + + atomic_dec(&cor_packets_in_workqueue); +} + +int cor_rcv_announce(struct sk_buff *skb) +{ + struct cor_skb_procstate *ps = cor_skb_pstate(skb); + long queuelen; + + queuelen = atomic_inc_return(&cor_packets_in_workqueue); + + BUG_ON(queuelen <= 0); + + if (queuelen > MAX_PACKETS_IN_ANNOUNCE_RCVQUEUE) { + atomic_dec(&cor_packets_in_workqueue); + kfree_skb(skb); + return NET_RX_SUCCESS; + } + + INIT_WORK(&(ps->funcstate.announce1.work), _cor_rcv_announce); + schedule_work(&(ps->funcstate.announce1.work)); + return NET_RX_SUCCESS; +} + + +int __init cor_neigh_ann_rcv_init(void) +{ + cor_nb_dd_slab = kmem_cache_create("cor_neighbor_discoverydata", + sizeof(struct cor_neighbor_discdata), 8, 0, 0); + if (unlikely(cor_nb_dd_slab == 0)) + return -ENOMEM; + + return 0; +} + +void __exit cor_neigh_ann_rcv_exit2(void) +{ + kmem_cache_destroy(cor_nb_dd_slab); + cor_nb_dd_slab = 0; +} diff --git a/net/cor/neigh_ann_snd.c b/net/cor/neigh_ann_snd.c new file mode 100644 index 000000000000..3929f98776de --- /dev/null +++ b/net/cor/neigh_ann_snd.c @@ -0,0 +1,275 @@ +/** + * Connection oriented routing + * Copyright (C) 2007-2021 Michael Blizek + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + + #include "cor.h" + +static DEFINE_SPINLOCK(cor_announce_snd_lock); +static LIST_HEAD(cor_announce_out_list); + +static int ___cor_send_announce(struct sk_buff *skb, int *sent) +{ + int rc; + struct cor_qos_queue *q = cor_get_queue(skb->dev); + + if (q == 0) { + kfree_skb(skb); + *sent = 1; + return NET_XMIT_SUCCESS; + } + + rc = cor_dev_queue_xmit(skb, q, QOS_CALLER_ANNOUNCE); + kref_put(&(q->ref), cor_free_qos); + if (rc != NET_XMIT_DROP) + *sent = 1; + + return rc; +} + +static int __cor_send_announce(struct cor_announce_data *ann, int *sent) +{ + __u32 len; + __u32 offset = 0; + + __u32 local_addrlen_tmp; + + char *msg = 0; + + struct sk_buff *skb; + __u32 headroom; + + headroom = LL_RESERVED_SPACE(ann->dev) + + ann->dev->needed_tailroom; + + spin_lock_bh(&cor_local_addr_lock); + +retry: + BUG_ON(cor_local_addrlen > 64); + + local_addrlen_tmp = cor_local_addrlen; + + spin_unlock_bh(&cor_local_addr_lock); + + len = 1 + 4 + 8 + 6 + local_addrlen_tmp; + + BUG_ON(len > 1024); + + skb = alloc_skb(headroom + len, GFP_ATOMIC); + if (unlikely(skb == 0)) + return NET_XMIT_SUCCESS; + + skb->protocol = htons(ETH_P_COR); + skb->dev = ann->dev; + skb_reserve(skb, headroom); + + #warning net_device locking? (other places too) + if(unlikely(dev_hard_header(skb, ann->dev, ETH_P_COR, + ann->mac, ann->dev->dev_addr, skb->len) < 0)) + goto out_err; + + skb_reset_network_header(skb); + + msg = skb_put(skb, len); + if (unlikely(msg == 0)) + goto out_err; + + spin_lock_bh(&cor_local_addr_lock); + + if (unlikely(cor_local_addrlen != local_addrlen_tmp)) { + kfree_skb(skb); + skb = 0; + msg = 0; + goto retry; + } + + msg[0] = PACKET_TYPE_ANNOUNCE; + offset++; + + cor_put_be32(msg + offset, cor_local_addr_sessionid); /* sessionid */ + offset += 4; + + cor_put_u16(msg + offset, ANNCMD_VERSION); /* command */ + offset += 2; + cor_put_u16(msg + offset, 4); /* command length */ + offset += 2; + cor_put_u16(msg + offset, 0); /* version */ + offset += 2; + cor_put_u16(msg + offset, 0); /* minversion */ + offset += 2; + + cor_put_u16(msg + offset, ANNCMD_ADDR); /* command */ + offset += 2; + cor_put_u16(msg + offset, 2 + cor_local_addrlen); /* command length */ + offset += 2; + cor_put_u16(msg + offset, cor_local_addrlen); /* addrlen */ + offset += 2; + if (cor_local_addrlen != 0) { + /* addr */ + memcpy(msg + offset, cor_local_addr, cor_local_addrlen); + offset += cor_local_addrlen; + } + + spin_unlock_bh(&cor_local_addr_lock); + + BUG_ON(offset != len); + + return ___cor_send_announce(skb, sent); + + if (0) { +out_err: + kfree_skb(skb); + return NET_XMIT_SUCCESS; + } +} + +void cor_announce_data_free(struct kref *ref) +{ + struct cor_announce_data *ann = container_of(ref, + struct cor_announce_data, ref); + kfree(ann); +} + +int _cor_send_announce(struct cor_announce_data *ann, int fromqos, int *sent) +{ + int reschedule = 0; + int rc = 0; + + spin_lock_bh(&(cor_announce_snd_lock)); + + if (unlikely(ann->dev == 0)) { + rc = NET_XMIT_SUCCESS; + goto out; + } + + if (cor_is_device_configurated(ann->dev) == 0) + rc = NET_XMIT_SUCCESS; + else if (fromqos == 0 && + cor_qos_fastsend_allowed_announce(ann->dev) == 0) + rc = NET_XMIT_DROP; + else + rc = __cor_send_announce(ann, sent); + + if (rc != NET_XMIT_DROP && ann->type != ANNOUNCE_TYPE_BROADCAST) { + ann->sndcnt++; + reschedule = (ann->sndcnt < ANNOUNCE_SEND_UNICAST_MAXCNT ? + 1 : 0); + + if (reschedule == 0) { + dev_put(ann->dev); + ann->dev = 0; + + list_del(&(ann->lh)); + kref_put(&(ann->ref), cor_kreffree_bug); + } + } else { + reschedule = 1; + } + +out: + spin_unlock_bh(&(cor_announce_snd_lock)); + + if (unlikely(reschedule == 0)) { + kref_put(&(ann->ref), cor_announce_data_free); + } else if (rc == NET_XMIT_DROP) { + if (fromqos == 0) { + struct cor_qos_queue *q = cor_get_queue(ann->dev); + if (q != 0) { + cor_qos_enqueue(q, &(ann->rb), ns_to_ktime(0), + QOS_CALLER_ANNOUNCE); + kref_put(&(q->ref), cor_free_qos); + } + } + } else { + schedule_delayed_work(&(ann->announce_work), msecs_to_jiffies( + ANNOUNCE_SEND_PACKETINTELVAL_MS)); + } + + if (rc != NET_XMIT_SUCCESS) + return QOS_RESUME_CONG; + + return QOS_RESUME_DONE; +} + +static void cor_send_announce(struct work_struct *work) +{ + struct cor_announce_data *ann = container_of(to_delayed_work(work), + struct cor_announce_data, announce_work); + int sent = 0; + _cor_send_announce(ann, 0, &sent); +} + +void cor_announce_send_start(struct net_device *dev, char *mac, int type) +{ + struct cor_announce_data *ann; + + ann = kmalloc(sizeof(struct cor_announce_data), GFP_KERNEL); + + if (unlikely(ann == 0)) { + printk(KERN_ERR "cor cannot allocate memory for sending " + "announces"); + return; + } + + memset(ann, 0, sizeof(struct cor_announce_data)); + + kref_init(&(ann->ref)); + + dev_hold(dev); + ann->dev = dev; + memcpy(ann->mac, mac, MAX_ADDR_LEN); + ann->type = type; + + spin_lock_bh(&(cor_announce_snd_lock)); + list_add_tail(&(ann->lh), &cor_announce_out_list); + spin_unlock_bh(&(cor_announce_snd_lock)); + + INIT_DELAYED_WORK(&(ann->announce_work), cor_send_announce); + kref_get(&(ann->ref)); + schedule_delayed_work(&(ann->announce_work), 1); +} + +void cor_announce_send_stop(struct net_device *dev, char *mac, int type) +{ + struct list_head *lh; + + spin_lock_bh(&(cor_announce_snd_lock)); + + lh = cor_announce_out_list.next; + while (lh != &cor_announce_out_list) { + struct cor_announce_data *ann = container_of(lh, + struct cor_announce_data, lh); + + lh = lh->next; + + + if (dev != 0 && (ann->dev != dev || ( + type != ANNOUNCE_TYPE_BROADCAST && ( + ann->type != type || + memcmp(ann->mac, mac, MAX_ADDR_LEN) != 0)))) + continue; + + dev_put(ann->dev); + ann->dev = 0; + + list_del(&(ann->lh)); + kref_put(&(ann->ref), cor_kreffree_bug); + } + + spin_unlock_bh(&(cor_announce_snd_lock)); +} diff --git a/net/cor/neighbor.c b/net/cor/neighbor.c index 84e0ccbbb62e..9afb8c02fc47 100644 --- a/net/cor/neighbor.c +++ b/net/cor/neighbor.c @@ -21,71 +21,11 @@ #include #include "cor.h" -/** - * Broadcast data format: - * version [2] - * is 0, may be increased if the protocol changes - * min_version [2] - * is 0, must be increased if a future version of the protocol is incompatible - * to the current version - * [data] - * - * Data format of the announce packet "data" field: - *{command [2] commandlength [2] commanddata [commandlength]}[...] - */ - -/* Commands */ - -/* NEIGHCMD_VERSION: version[2] minversion[2] */ -#define NEIGHCMD_VERSION 1 - -/* NEIGHCMD_ADDR: addrlen[2] addr[addrlen] */ -#define NEIGHCMD_ADDR 2 - - -struct cor_neighbor_discdata{ - struct list_head lh; - unsigned long jiffies_created; - - __be32 sessionid; - struct net_device *dev; - char mac[MAX_ADDR_LEN]; - - __u8 nb_allocated; - - __u8 rcvd_version; - __u8 rcvd_addr; - - __u16 version; - __u16 minversion; - - char *addr; - __u16 addrlen; -}; - -static atomic_t cor_packets_in_workqueue = ATOMIC_INIT(0); - -static DEFINE_MUTEX(cor_announce_rcv_lock); -static DEFINE_SPINLOCK(cor_announce_snd_lock); static DEFINE_SPINLOCK(cor_neighbor_list_lock); - -static DEFINE_MUTEX(cor_neigh_up_lock); - -static DEFINE_SPINLOCK(cor_local_addr_lock); -static char *cor_local_addr; -static __u32 cor_local_addrlen; -static __be32 cor_local_addr_sessionid; - -static LIST_HEAD(cor_nb_dd_list); /* protected by cor_announce_rcv_lock */ -static __u32 cor_num_nb_dd = 0; -static struct kmem_cache *cor_nb_dd_slab; - static LIST_HEAD(cor_nb_list); static struct kmem_cache *cor_nb_slab; -static atomic_t cor_num_neighs; - -static LIST_HEAD(cor_announce_out_list); +atomic_t cor_num_neighs; void cor_neighbor_free(struct kref *ref) @@ -240,7 +180,7 @@ int cor_is_from_nb(struct sk_buff *skb, struct cor_neighbor *nb) return rc; } -static struct cor_neighbor *_cor_get_neigh_by_mac(struct net_device *dev, +struct cor_neighbor *_cor_get_neigh_by_mac(struct net_device *dev, char *source_hw) { struct list_head *currlh; @@ -1037,7 +977,7 @@ unsigned long cor_get_next_ping_time(struct cor_neighbor *nb) return nb->last_ping_time + msecs_to_jiffies(forcetime); } -static void cor_add_neighbor(struct cor_neighbor_discdata *nb_dd) +void cor_add_neighbor(struct cor_neighbor_discdata *nb_dd) { struct cor_neighbor *nb; struct list_head *currlh; @@ -1118,628 +1058,6 @@ already_present: spin_unlock_bh(&cor_neighbor_list_lock); } -static int cor_parse_announce_version(struct cor_neighbor_discdata *nb_dd, - __u16 cmd, char *cmddata, __u16 len) -{ - __u16 version; - __u16 minversion; - - if (unlikely(len < 4)) - return 1; - - version = cor_parse_u16(cmddata); - cmddata += 2; - len -= 2; - minversion = cor_parse_u16(cmddata); - cmddata += 2; - len -= 2; - - if (minversion != 0) - return 1; - - if (nb_dd->rcvd_version != 0) { - if (nb_dd->version != version || - nb_dd->minversion != minversion) - return 1; - } else { - nb_dd->version = version; - nb_dd->minversion = minversion; - nb_dd->rcvd_version = 1; - } - - return 0; -} - -static int cor_parse_announce_addaddr(struct cor_neighbor_discdata *nb_dd, - __u16 cmd, char *cmddata, __u16 len) -{ - __u16 addrlen; - char *addr; - - BUG_ON(cmd != NEIGHCMD_ADDR); - BUG_ON((nb_dd->addr == 0) != (nb_dd->addrlen == 0)); - BUG_ON(nb_dd->rcvd_addr == 0 && nb_dd->addr != 0); - - if (len < 2) - return 1; - - addrlen = cor_parse_u16(cmddata); - cmddata += 2; - len -= 2; - - if (len < addrlen) - return 1; - - addr = cmddata; - cmddata += addrlen; - len -= addrlen; - - if (nb_dd->rcvd_addr != 0) { - if (nb_dd->addrlen != addrlen) - return 1; - if (addrlen != 0 && memcmp(nb_dd->addr, addr, addrlen) != 0) - return 1; - } else { - if (addrlen != 0) { - nb_dd->addr = kmalloc(addrlen, GFP_KERNEL); - if (unlikely(nb_dd->addr == 0)) - return 1; - - memcpy(nb_dd->addr, addr, addrlen); - } - nb_dd->addrlen = addrlen; - - nb_dd->rcvd_addr = 1; - } - - return 0; -} - -static int cor_parse_announce_cmd(struct cor_neighbor_discdata *nb_dd, - __u16 cmd, char *cmddata, __u16 len) -{ - if (cmd == NEIGHCMD_VERSION) { - return cor_parse_announce_version(nb_dd, cmd, cmddata, len); - } else if (cmd == NEIGHCMD_ADDR) { - return cor_parse_announce_addaddr(nb_dd, cmd, cmddata, len); - } else { - return 1; - } -} - -static int cor_parse_announce_cmds(struct cor_neighbor_discdata *nb_dd, - char *msg, __u32 len) -{ - __u32 zeros = 0; - while (zeros < len) { - if (msg[len-zeros-1] != 0) - break; - zeros++; - } - - while (len >= 4 && len > zeros) { - __u16 cmd; - __u16 cmdlen; - - cmd = cor_parse_u16(msg); - msg += 2; - len -= 2; - cmdlen = cor_parse_u16(msg); - msg += 2; - len -= 2; - - if (cmdlen > len) - return 1; - - if (cor_parse_announce_cmd(nb_dd, cmd, msg, cmdlen) != 0) - return 1; - - msg += cmdlen; - len -= cmdlen; - } - - if (len != 0 && len < zeros) - return 1; - - return 0; -} - -static void cor_neighbor_discdata_free(struct cor_neighbor_discdata *nb_dd) -{ - list_del(&(nb_dd->lh)); - - BUG_ON(nb_dd->dev == 0); - dev_put(nb_dd->dev); - - if (nb_dd->addr != 0) { - kfree(nb_dd->addr); - nb_dd->addr = 0; - nb_dd->addrlen = 0; - } - - kmem_cache_free(cor_nb_dd_slab, nb_dd); - - BUG_ON(cor_num_nb_dd == 0); - cor_num_nb_dd--; -} - -static struct cor_neighbor_discdata *cor_findoralloc_neighbor_discdata( - struct net_device *dev, char *source_hw, __be32 sessionid) -{ - unsigned long jiffies_tmp = jiffies; - struct list_head *currlh; - - __u32 neighs; - struct cor_neighbor_discdata *nb_dd; - - currlh = cor_nb_dd_list.next; - while (currlh != &cor_nb_dd_list) { - struct cor_neighbor_discdata *curr = container_of(currlh, - struct cor_neighbor_discdata, lh); - - currlh = currlh->next; - - if (time_after(jiffies_tmp, curr->jiffies_created + - HZ * NEIGHBOR_DISCOVERY_TIMEOUT_SEC)) { - cor_neighbor_discdata_free(curr); - continue; - } - - if (curr->sessionid == sessionid && curr->dev == dev && - memcmp(curr->mac, source_hw, MAX_ADDR_LEN) == 0) - return curr; - } - - neighs = atomic_read(&cor_num_neighs); - if (neighs + cor_num_nb_dd < neighs || - neighs + cor_num_nb_dd >= MAX_NEIGHBORS) - return 0; - cor_num_nb_dd++; - - nb_dd = kmem_cache_alloc(cor_nb_dd_slab, GFP_KERNEL); - if (unlikely(nb_dd == 0)) - return 0; - - memset(nb_dd, 0, sizeof(struct cor_neighbor_discdata)); - - nb_dd->sessionid = sessionid; - - dev_hold(dev); - nb_dd->dev = dev; - - memcpy(nb_dd->mac, source_hw, MAX_ADDR_LEN); - - list_add_tail(&(nb_dd->lh), &cor_nb_dd_list); - nb_dd->jiffies_created = jiffies_tmp; - - if (cor_is_clientmode()) - cor_announce_send_start(dev, source_hw, ANNOUNCE_TYPE_UNICAST); - - return nb_dd; -} - -static void cor_parse_announce(struct net_device *dev, char *source_hw, - char *msg, __u32 len) -{ - __be32 sessionid; - struct cor_neighbor_discdata *nb_dd; - - - if (unlikely(len < 4)) - return; - - sessionid = cor_parse_be32(msg); - msg += 4; - len -= 4; - - nb_dd = cor_findoralloc_neighbor_discdata(dev, source_hw, sessionid); - if (unlikely(nb_dd == 0)) - return; - - if (cor_parse_announce_cmds(nb_dd, msg, len) != 0) - goto error; - - if (nb_dd->rcvd_version != 0 && nb_dd->rcvd_addr != 0) { - cor_add_neighbor(nb_dd); - -error: - cor_neighbor_discdata_free(nb_dd); - } -} - -static void _cor_rcv_announce(struct work_struct *work) -{ - struct cor_skb_procstate *ps = container_of(work, - struct cor_skb_procstate, funcstate.announce1.work); - struct sk_buff *skb = cor_skb_from_pstate(ps); - - char source_hw[MAX_ADDR_LEN]; - - struct cor_neighbor *nb; - - char *msg; - __u16 len; - - if (cor_is_device_configurated(skb->dev) == 0) - goto discard; - - memset(source_hw, 0, MAX_ADDR_LEN); - if (skb->dev->header_ops != 0 && - skb->dev->header_ops->parse != 0) - skb->dev->header_ops->parse(skb, source_hw); - - nb = _cor_get_neigh_by_mac(skb->dev, source_hw); - if (nb != 0) { - kref_put(&(nb->ref), cor_neighbor_free); - nb = 0; - goto discard; - } - - if (unlikely(skb->len > 65535 || skb->len < 0)) - goto discard; - len = (__u16) skb->len; - - msg = cor_pull_skb(skb, len); - if (msg == 0) - goto discard; - - mutex_lock(&(cor_announce_rcv_lock)); - cor_parse_announce(skb->dev, source_hw, msg, len); - mutex_unlock(&(cor_announce_rcv_lock)); - - discard: - kfree_skb(skb); - - atomic_dec(&cor_packets_in_workqueue); -} - -int cor_rcv_announce(struct sk_buff *skb) -{ - struct cor_skb_procstate *ps = cor_skb_pstate(skb); - long queuelen; - - queuelen = atomic_inc_return(&cor_packets_in_workqueue); - - BUG_ON(queuelen <= 0); - - if (queuelen > MAX_PACKETS_IN_ANNOUNCE_RCVQUEUE) { - atomic_dec(&cor_packets_in_workqueue); - kfree_skb(skb); - return NET_RX_SUCCESS; - } - - INIT_WORK(&(ps->funcstate.announce1.work), _cor_rcv_announce); - schedule_work(&(ps->funcstate.announce1.work)); - return NET_RX_SUCCESS; -} - -static int ___cor_send_announce(struct sk_buff *skb, int *sent) -{ - int rc; - struct cor_qos_queue *q = cor_get_queue(skb->dev); - - if (q == 0) { - kfree_skb(skb); - *sent = 1; - return NET_XMIT_SUCCESS; - } - - rc = cor_dev_queue_xmit(skb, q, QOS_CALLER_ANNOUNCE); - kref_put(&(q->ref), cor_free_qos); - if (rc != NET_XMIT_DROP) - *sent = 1; - - return rc; -} - -static int __cor_send_announce(struct cor_announce_data *ann, int *sent) -{ - __u32 len; - __u32 offset = 0; - - __u32 local_addrlen_tmp; - - char *msg = 0; - - struct sk_buff *skb; - __u32 headroom; - - headroom = LL_RESERVED_SPACE(ann->dev) + - ann->dev->needed_tailroom; - - spin_lock_bh(&cor_local_addr_lock); - -retry: - BUG_ON(cor_local_addrlen > 64); - - local_addrlen_tmp = cor_local_addrlen; - - spin_unlock_bh(&cor_local_addr_lock); - - len = 1 + 4 + 8 + 6 + local_addrlen_tmp; - - BUG_ON(len > 1024); - - skb = alloc_skb(headroom + len, GFP_ATOMIC); - if (unlikely(skb == 0)) - return NET_XMIT_SUCCESS; - - skb->protocol = htons(ETH_P_COR); - skb->dev = ann->dev; - skb_reserve(skb, headroom); - - #warning net_device locking? (other places too) - if(unlikely(dev_hard_header(skb, ann->dev, ETH_P_COR, - ann->mac, ann->dev->dev_addr, skb->len) < 0)) - goto out_err; - - skb_reset_network_header(skb); - - msg = skb_put(skb, len); - if (unlikely(msg == 0)) - goto out_err; - - spin_lock_bh(&cor_local_addr_lock); - - if (unlikely(cor_local_addrlen != local_addrlen_tmp)) { - kfree_skb(skb); - skb = 0; - msg = 0; - goto retry; - } - - msg[0] = PACKET_TYPE_ANNOUNCE; - offset++; - - cor_put_be32(msg + offset, cor_local_addr_sessionid); /* sessionid */ - offset += 4; - - cor_put_u16(msg + offset, NEIGHCMD_VERSION); /* command */ - offset += 2; - cor_put_u16(msg + offset, 4); /* command length */ - offset += 2; - cor_put_u16(msg + offset, 0); /* version */ - offset += 2; - cor_put_u16(msg + offset, 0); /* minversion */ - offset += 2; - - cor_put_u16(msg + offset, NEIGHCMD_ADDR); /* command */ - offset += 2; - cor_put_u16(msg + offset, 2 + cor_local_addrlen); /* command length */ - offset += 2; - cor_put_u16(msg + offset, cor_local_addrlen); /* addrlen */ - offset += 2; - if (cor_local_addrlen != 0) { - /* addr */ - memcpy(msg + offset, cor_local_addr, cor_local_addrlen); - offset += cor_local_addrlen; - } - - spin_unlock_bh(&cor_local_addr_lock); - - BUG_ON(offset != len); - - return ___cor_send_announce(skb, sent); - - if (0) { -out_err: - kfree_skb(skb); - return NET_XMIT_SUCCESS; - } -} - -void cor_announce_data_free(struct kref *ref) -{ - struct cor_announce_data *ann = container_of(ref, - struct cor_announce_data, ref); - kfree(ann); -} - -int _cor_send_announce(struct cor_announce_data *ann, int fromqos, int *sent) -{ - int reschedule = 0; - int rc = 0; - - spin_lock_bh(&(cor_announce_snd_lock)); - - if (unlikely(ann->dev == 0)) { - rc = NET_XMIT_SUCCESS; - goto out; - } - - if (cor_is_device_configurated(ann->dev) == 0) - rc = NET_XMIT_SUCCESS; - else if (fromqos == 0 && - cor_qos_fastsend_allowed_announce(ann->dev) == 0) - rc = NET_XMIT_DROP; - else - rc = __cor_send_announce(ann, sent); - - if (rc != NET_XMIT_DROP && ann->type != ANNOUNCE_TYPE_BROADCAST) { - ann->sndcnt++; - reschedule = (ann->sndcnt < ANNOUNCE_SEND_UNICAST_MAXCNT ? - 1 : 0); - - if (reschedule == 0) { - dev_put(ann->dev); - ann->dev = 0; - - list_del(&(ann->lh)); - kref_put(&(ann->ref), cor_kreffree_bug); - } - } else { - reschedule = 1; - } - -out: - spin_unlock_bh(&(cor_announce_snd_lock)); - - if (unlikely(reschedule == 0)) { - kref_put(&(ann->ref), cor_announce_data_free); - } else if (rc == NET_XMIT_DROP) { - if (fromqos == 0) { - struct cor_qos_queue *q = cor_get_queue(ann->dev); - if (q != 0) { - cor_qos_enqueue(q, &(ann->rb), ns_to_ktime(0), - QOS_CALLER_ANNOUNCE); - kref_put(&(q->ref), cor_free_qos); - } - } - } else { - schedule_delayed_work(&(ann->announce_work), msecs_to_jiffies( - ANNOUNCE_SEND_PACKETINTELVAL_MS)); - } - - if (rc != NET_XMIT_SUCCESS) - return QOS_RESUME_CONG; - - return QOS_RESUME_DONE; -} - -static void cor_send_announce(struct work_struct *work) -{ - struct cor_announce_data *ann = container_of(to_delayed_work(work), - struct cor_announce_data, announce_work); - int sent = 0; - _cor_send_announce(ann, 0, &sent); -} - -void cor_announce_send_start(struct net_device *dev, char *mac, int type) -{ - struct cor_announce_data *ann; - - ann = kmalloc(sizeof(struct cor_announce_data), GFP_KERNEL); - - if (unlikely(ann == 0)) { - printk(KERN_ERR "cor cannot allocate memory for sending " - "announces"); - return; - } - - memset(ann, 0, sizeof(struct cor_announce_data)); - - kref_init(&(ann->ref)); - - dev_hold(dev); - ann->dev = dev; - memcpy(ann->mac, mac, MAX_ADDR_LEN); - ann->type = type; - - spin_lock_bh(&(cor_announce_snd_lock)); - list_add_tail(&(ann->lh), &cor_announce_out_list); - spin_unlock_bh(&(cor_announce_snd_lock)); - - INIT_DELAYED_WORK(&(ann->announce_work), cor_send_announce); - kref_get(&(ann->ref)); - schedule_delayed_work(&(ann->announce_work), 1); -} - -void cor_announce_send_stop(struct net_device *dev, char *mac, int type) -{ - struct list_head *lh; - - spin_lock_bh(&(cor_announce_snd_lock)); - - lh = cor_announce_out_list.next; - while (lh != &cor_announce_out_list) { - struct cor_announce_data *ann = container_of(lh, - struct cor_announce_data, lh); - - lh = lh->next; - - - if (dev != 0 && (ann->dev != dev || ( - type != ANNOUNCE_TYPE_BROADCAST && ( - ann->type != type || - memcmp(ann->mac, mac, MAX_ADDR_LEN) != 0)))) - continue; - - dev_put(ann->dev); - ann->dev = 0; - - list_del(&(ann->lh)); - kref_put(&(ann->ref), cor_kreffree_bug); - } - - spin_unlock_bh(&(cor_announce_snd_lock)); -} - -void _cor_neighbor_down(void) -{ - cor_dev_down(); - - spin_lock_bh(&cor_local_addr_lock); - if (cor_local_addr != 0) { - kfree(cor_local_addr); - cor_local_addr = 0; - } - cor_local_addrlen = 0; - spin_unlock_bh(&cor_local_addr_lock); - - cor_reset_neighbors(0); - cor_reset_neighbors(0); - cor_destroy_queue(0); - - cor_announce_send_stop(0, 0, ANNOUNCE_TYPE_BROADCAST); -} - -void cor_neighbor_down(void) -{ - mutex_lock(&(cor_neigh_up_lock)); - _cor_neighbor_down(); - mutex_unlock(&(cor_neigh_up_lock)); -} - -int cor_neighbor_up(char *addr2, __u32 addrlen2) -{ - int rc = 0; - - char *addr2_copy = kmalloc(addrlen2, GFP_KERNEL); - if (unlikely(addr2_copy == 0)) - return 1; - - memcpy(addr2_copy, addr2, addrlen2); - - mutex_lock(&(cor_neigh_up_lock)); - - _cor_neighbor_down(); - - spin_lock_bh(&cor_local_addr_lock); - - BUG_ON(cor_local_addr != 0); - BUG_ON(cor_local_addrlen != 0); - - cor_local_addr = addr2_copy; - addr2_copy = 0; - cor_local_addrlen = addrlen2; - get_random_bytes((char *) &cor_local_addr_sessionid, - sizeof(cor_local_addr_sessionid)); - - spin_unlock_bh(&cor_local_addr_lock); - - if (cor_dev_up() != 0) { - spin_lock_bh(&cor_local_addr_lock); - kfree(cor_local_addr); - cor_local_addr = 0; - cor_local_addrlen = 0; - spin_unlock_bh(&cor_local_addr_lock); - rc = 1; - } - - mutex_unlock(&(cor_neigh_up_lock)); - - return rc; -} - -int cor_is_clientmode(void) -{ - int rc; - spin_lock_bh(&cor_local_addr_lock); - rc = (cor_local_addrlen == 0 ? 1 : 0); - spin_unlock_bh(&cor_local_addr_lock); - return rc; -} - int __init cor_neighbor_init(void) { cor_nb_slab = kmem_cache_create("cor_neighbor", @@ -1747,28 +1065,15 @@ int __init cor_neighbor_init(void) if (unlikely(cor_nb_slab == 0)) return -ENOMEM; - cor_nb_dd_slab = kmem_cache_create("cor_neighbor_discoverydata", - sizeof(struct cor_neighbor_discdata), 8, 0, 0); - if (unlikely(cor_nb_dd_slab == 0)) - return -ENOMEM; - atomic_set(&cor_num_neighs, 0); return 0; } -void __exit cor_neighbor_exit1(void) -{ - flush_scheduled_work(); -} - void __exit cor_neighbor_exit2(void) { BUG_ON(atomic_read(&cor_num_neighs) != 0); - kmem_cache_destroy(cor_nb_dd_slab); - cor_nb_dd_slab = 0; - kmem_cache_destroy(cor_nb_slab); cor_nb_slab = 0; } diff --git a/net/cor/sock_rdaemon.c b/net/cor/sock_rdaemon.c index f92e77a6567a..4b5d94601834 100644 --- a/net/cor/sock_rdaemon.c +++ b/net/cor/sock_rdaemon.c @@ -64,75 +64,15 @@ static DEFINE_MUTEX(cor_rds_lock); static struct cor_rdsock *cor_crd = 0; -struct cor_interface_config { - char *name; - __u32 name_len; -}; - -static DEFINE_SPINLOCK(cor_interface_config_lock); -static struct cor_interface_config *cor_interface_config = 0; -static __u32 cor_num_interfaces = 0; -static int cor_all_interfaces = 0; - -static void cor_reset_interface_config(void); - -int cor_is_device_configurated(struct net_device *dev) -{ - int ret = 0; - - unsigned long iflags; - - __u32 i; - spin_lock_irqsave(&cor_interface_config_lock, iflags); - - if (cor_all_interfaces != 0) { - ret = 1; - goto out; - } - - BUG_ON(cor_num_interfaces > 65536); - for (i=0;iname == 0); - - for (j=0;;j++) { - if (j >= sizeof(dev->name)) - break; - - if (dev->name[j] == 0 && j == curr->name_len) { - ret = 1; - goto out; - } - - if (dev->name[j] == 0 || j >= curr->name_len) - break; - - if (dev->name[j] != curr->name[j]) - break; - } - } - -out: - spin_unlock_irqrestore(&cor_interface_config_lock, iflags); - - return ret; -} - int cor_rd_socket_release(struct socket *sock) { - unsigned long iflags; - mutex_lock(&cor_rds_lock); BUG_ON(((struct cor_rdsock *) sock->sk) != cor_crd); - cor_neighbor_down(); + cor_config_down(); - spin_lock_irqsave(&cor_interface_config_lock, iflags); - cor_reset_interface_config(); - spin_unlock_irqrestore(&cor_interface_config_lock, iflags); + cor_set_interface_config(0, 0, 0); while (list_empty(&(cor_crd->rcv_msgs)) == 0) { struct cor_rd_msg *rdm = container_of(cor_crd->rcv_msgs.next, @@ -257,31 +197,11 @@ err: } /* interface_config_lock must be held */ -static void cor_reset_interface_config(void) -{ - __u32 i; - - cor_all_interfaces = 0; - BUG_ON(cor_num_interfaces > 65536); - for (i=0;iname == 0); - kfree(curr->name); - curr->name = 0; - } - - kfree(cor_interface_config); - cor_interface_config = 0; - cor_num_interfaces = 0; -} static int _cor_rd_parse_up_interfaces(struct cor_rdsock *crd, char *param, __u32 paramlen, __u32 *offset) { - unsigned long iflags; - __u32 num_intf; __u32 i; struct cor_interface_config *newconfig = 0; @@ -324,12 +244,7 @@ static int _cor_rd_parse_up_interfaces(struct cor_rdsock *crd, char *param, *offset += newconfig_curr->name_len; } - spin_lock_irqsave(&cor_interface_config_lock, iflags); - cor_reset_interface_config(); - cor_all_interfaces = 0; - cor_interface_config = newconfig; - cor_num_interfaces = num_intf; - spin_unlock_irqrestore(&cor_interface_config_lock, iflags); + cor_set_interface_config(newconfig, num_intf, 0); return 0; @@ -381,15 +296,10 @@ static int cor_rd_parse_up(struct cor_rdsock *crd, __u32 cmd, return 1; } } else { - unsigned long iflags; - - spin_lock_irqsave(&cor_interface_config_lock, iflags); - cor_reset_interface_config(); - cor_all_interfaces = 1; - spin_unlock_irqrestore(&cor_interface_config_lock, iflags); + cor_set_interface_config(0, 0, 1); } - if (cor_neighbor_up(addr, addrlen) != 0) + if (cor_config_up(addr, addrlen) != 0) return 1; return 0; -- 2.11.4.GIT