summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--accel-pppd/ctrl/ipoe/dhcpv4.c17
-rw-r--r--accel-pppd/ctrl/ipoe/ipoe.c64
-rw-r--r--drivers/ipoe/ipoe.c31
3 files changed, 79 insertions, 33 deletions
diff --git a/accel-pppd/ctrl/ipoe/dhcpv4.c b/accel-pppd/ctrl/ipoe/dhcpv4.c
index f5408b08..fa763445 100644
--- a/accel-pppd/ctrl/ipoe/dhcpv4.c
+++ b/accel-pppd/ctrl/ipoe/dhcpv4.c
@@ -41,6 +41,7 @@ static mempool_t pack_pool;
static mempool_t opt_pool;
static LIST_HEAD(relay_list);
+static pthread_mutex_t relay_lock = PTHREAD_MUTEX_INITIALIZER;
static int dhcpv4_read(struct triton_md_handler_t *h);
int dhcpv4_packet_add_opt(struct dhcpv4_packet *pack, int type, const void *data, int len);
@@ -838,6 +839,7 @@ struct dhcpv4_relay *dhcpv4_relay_create(const char *_addr, const char *_giaddr,
laddr.sin_addr.s_addr = giaddr;
laddr.sin_port = htons(DHCP_SERV_PORT);
+ pthread_mutex_lock(&relay_lock);
list_for_each_entry(r, &relay_list, entry) {
if (r->addr == addr && r->giaddr == giaddr)
goto found;
@@ -852,7 +854,7 @@ struct dhcpv4_relay *dhcpv4_relay_create(const char *_addr, const char *_giaddr,
sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (!sock) {
log_error("socket: %s\n", strerror(errno));
- goto out_err;
+ goto out_err_unlock;
}
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &f, sizeof(f)))
@@ -860,12 +862,12 @@ struct dhcpv4_relay *dhcpv4_relay_create(const char *_addr, const char *_giaddr,
if (bind(sock, &laddr, sizeof(laddr))) {
log_error("dhcpv4: relay: %s: bind: %s\n", _addr, strerror(errno));
- goto out_err;
+ goto out_err_unlock;
}
if (connect(sock, &raddr, sizeof(raddr))) {
log_error("dhcpv4: relay: %s: connect: %s\n", _addr, strerror(errno));
- goto out_err;
+ goto out_err_unlock;
}
fcntl(sock, F_SETFL, O_NONBLOCK);
@@ -875,7 +877,7 @@ struct dhcpv4_relay *dhcpv4_relay_create(const char *_addr, const char *_giaddr,
r->hnd.read = dhcpv4_relay_read;
triton_context_register(&r->ctx, NULL);
- triton_md_register_handler(ctx, &r->hnd);
+ triton_md_register_handler(&r->ctx, &r->hnd);
triton_md_enable_handler(&r->hnd, MD_MODE_READ);
triton_context_wakeup(&r->ctx);
@@ -886,9 +888,14 @@ found:
c->ctx = ctx;
c->recv = recv;
list_add_tail(&c->entry, &r->ctx_list);
+
+ pthread_mutex_unlock(&relay_lock);
return r;
+out_err_unlock:
+ pthread_mutex_unlock(&relay_lock);
+
out_err:
if (sock != -1)
close(sock);
@@ -900,6 +907,7 @@ void dhcpv4_relay_free(struct dhcpv4_relay *r, struct triton_context_t *ctx)
{
struct dhcpv4_relay_ctx *c;
+ pthread_mutex_lock(&relay_lock);
list_for_each_entry(c, &r->ctx_list, entry) {
if (c->ctx == ctx) {
list_del(&c->entry);
@@ -916,6 +924,7 @@ void dhcpv4_relay_free(struct dhcpv4_relay *r, struct triton_context_t *ctx)
triton_context_unregister(&r->ctx);
_free(r);
}
+ pthread_mutex_unlock(&relay_lock);
}
int dhcpv4_relay_send(struct dhcpv4_relay *relay, struct dhcpv4_packet *request, uint32_t server_id, const char *agent_circuit_id, const char *agent_remote_id)
diff --git a/accel-pppd/ctrl/ipoe/ipoe.c b/accel-pppd/ctrl/ipoe/ipoe.c
index f792e1bc..5e88f5d9 100644
--- a/accel-pppd/ctrl/ipoe/ipoe.c
+++ b/accel-pppd/ctrl/ipoe/ipoe.c
@@ -56,7 +56,6 @@ struct iplink_arg {
pcre *re;
const char *opt;
long *arg1;
- int arg2;
};
struct unit_cache {
@@ -685,7 +684,7 @@ static void ipoe_ifcfg_add(struct ipoe_session *ses)
ses->ifcfg = 1;
}
-static void ipoe_ifcfg_del(struct ipoe_session *ses)
+static void ipoe_ifcfg_del(struct ipoe_session *ses, int lock)
{
struct ipoe_serv *serv = ses->serv;
@@ -696,10 +695,14 @@ static void ipoe_ifcfg_del(struct ipoe_session *ses)
if (ses->serv->opt_shared) {
ipoe_serv_del_addr(ses->serv, ses->siaddr);
} else {
- pthread_mutex_lock(&serv->lock);
- if (ipaddr_del(serv->ifindex, ses->siaddr))
- log_ppp_warn("ipoe: failed to remove addess from interface '%s'\n", serv->ifname);
- pthread_mutex_unlock(&serv->lock);
+ if (lock)
+ pthread_mutex_lock(&serv->lock);
+ if (ipaddr_del(serv->ifindex, ses->siaddr)) {
+ if (lock)
+ log_ppp_warn("ipoe: failed to remove addess from interface '%s'\n", serv->ifname);
+ }
+ if (lock)
+ pthread_mutex_unlock(&serv->lock);
}
}
}
@@ -848,7 +851,6 @@ static void ipoe_session_started(struct ap_session *s)
static void ipoe_session_free(struct ipoe_session *ses)
{
-
if (ses->started)
__sync_sub_and_fetch(&stat_active, 1);
else
@@ -906,7 +908,7 @@ static void ipoe_session_finished(struct ap_session *s)
dhcpv4_relay_send_release(ses->serv->dhcpv4_relay, ses->hwaddr, ses->xid, ses->yiaddr, ses->client_id, ses->relay_agent, ses->serv->ifname, conf_agent_remote_id);
if (ses->ifcfg)
- ipoe_ifcfg_del(ses);
+ ipoe_ifcfg_del(ses, 1);
if (ses->dhcpv4)
dhcpv4_free(ses->dhcpv4);
@@ -1655,7 +1657,7 @@ static void ipoe_serv_release(struct ipoe_serv *serv)
}
pthread_mutex_unlock(&serv->lock);
- if (serv->vid && !serv->need_close) {
+ if (serv->vid && !serv->need_close && !ap_shutdown) {
if (serv->timer.tpd)
triton_timer_mod(&serv->timer, 0);
else
@@ -1780,7 +1782,7 @@ static void ipoe_drop_sessions(struct ipoe_serv *serv, struct ipoe_session *skip
ses->terminating = 1;
if (ses->ifcfg) {
- ipoe_ifcfg_del(ses);
+ ipoe_ifcfg_del(ses, 0);
ses->ifcfg = 0;
}
@@ -1853,8 +1855,10 @@ void ipoe_vlan_notify(int ifindex, int vid)
log_info2("ipoe: create vlan %s\n", ifr.ifr_name);
- if (iplink_vlan_add(ifr.ifr_name, ifindex, vid))
+ if (iplink_vlan_add(ifr.ifr_name, ifindex, vid)) {
log_warn("ipoe: vlan-mon: %s: failed to add vlan\n", ifr.ifr_name);
+ return;
+ }
if (ioctl(sock_fd, SIOCGIFINDEX, &ifr, sizeof(ifr))) {
log_error("ipoe: vlan-mon: %s: failed to get interface index\n", ifr.ifr_name);
@@ -1993,6 +1997,7 @@ static void add_interface(const char *ifname, int ifindex, const char *opt, int
if (opt_up)
ipoe_nl_add_interface(ifindex);
+ pthread_mutex_lock(&serv_lock);
list_for_each_entry(serv, &serv_list, entry) {
if (strcmp(ifname, serv->ifname))
continue;
@@ -2044,8 +2049,10 @@ static void add_interface(const char *ifname, int ifindex, const char *opt, int
if (str0)
_free(str0);
+ pthread_mutex_unlock(&serv_lock);
return;
}
+ pthread_mutex_unlock(&serv_lock);
opt = strchr(opt, ',');
if (opt)
@@ -2117,7 +2124,9 @@ static void add_interface(const char *ifname, int ifindex, const char *opt, int
triton_context_wakeup(&serv->ctx);
+ pthread_mutex_lock(&serv_lock);
list_add_tail(&serv->entry, &serv_list);
+ pthread_mutex_unlock(&serv_lock);
if (str0)
_free(str0);
@@ -2436,9 +2445,9 @@ static int parse_vlan_mon(const char *opt, long *mask)
ptr = strchr(opt, 0);
if (*ptr == ',')
- memset(mask, 0xff, 4096/8/sizeof(long));
+ memset(mask, 0xff, 4096/8);
else if (*ptr == 0) {
- memset(mask, 0, 4096/8/sizeof(long));
+ memset(mask, 0, 4096/8);
return 0;
} else
goto out_err;
@@ -2458,10 +2467,10 @@ static int parse_vlan_mon(const char *opt, long *mask)
}
for (; vid < vid2; vid++)
- mask[vid / (8*sizeof(long))] &= ~(1 << (vid % (8*sizeof(long))));
+ mask[vid / (8*sizeof(long))] &= ~(1lu << (vid % (8*sizeof(long))));
}
- mask[vid / (8*sizeof(long))] &= ~(1 << (vid % (8*sizeof(long))));
+ mask[vid / (8*sizeof(long))] &= ~(1lu << (vid % (8*sizeof(long))));
if (*ptr2 == 0)
break;
@@ -2479,11 +2488,13 @@ out_err:
return -1;
}
-static void add_vlan_mon(const char *opt, long *mask, int len)
+static void add_vlan_mon(const char *opt, long *mask)
{
const char *ptr;
struct ifreq ifr;
int ifindex;
+ long mask1[4096/8/sizeof(long)];
+ struct ipoe_serv *serv;
for (ptr = opt; *ptr && *ptr != ','; ptr++);
@@ -2512,12 +2523,20 @@ static void add_vlan_mon(const char *opt, long *mask, int len)
ioctl(sock_fd, SIOCSIFFLAGS, &ifr);
}
- ipoe_nl_add_vlan_mon(ifindex, mask, len);
+ memcpy(mask1, mask, sizeof(mask1));
+ list_for_each_entry(serv, &serv_list, entry) {
+ if (serv->vid && serv->parent_ifindex == ifindex)
+ mask1[serv->vid / (8*sizeof(long))] |= 1lu << (serv->vid % (8*sizeof(long)));
+ }
+
+ ipoe_nl_add_vlan_mon(ifindex, mask1, sizeof(mask1));
}
static int __load_vlan_mon_re(int index, int flags, const char *name, struct iplink_arg *arg)
{
struct ifreq ifr;
+ long mask1[4096/8/sizeof(long)];
+ struct ipoe_serv *serv;
if (pcre_exec(arg->re, NULL, name, strlen(name), 0, 0, NULL, 0) < 0)
return 0;
@@ -2532,8 +2551,14 @@ static int __load_vlan_mon_re(int index, int flags, const char *name, struct ipl
ioctl(sock_fd, SIOCSIFFLAGS, &ifr);
}
+
+ memcpy(mask1, arg->arg1, sizeof(mask1));
+ list_for_each_entry(serv, &serv_list, entry) {
+ if (serv->vid && serv->parent_ifindex == index)
+ mask1[serv->vid / (8*sizeof(long))] |= 1lu << (serv->vid % (8*sizeof(long)));
+ }
- ipoe_nl_add_vlan_mon(index, arg->arg1, arg->arg2);
+ ipoe_nl_add_vlan_mon(index, mask1, sizeof(mask1));
return 0;
}
@@ -2563,7 +2588,6 @@ static void load_vlan_mon_re(const char *opt, long *mask, int len)
arg.re = re;
arg.opt = opt;
arg.arg1 = mask;
- arg.arg2 = len;
iplink_list((iplink_list_func)__load_vlan_mon_re, &arg);
@@ -2592,7 +2616,7 @@ static void load_vlan_mon(struct conf_sect_t *sect)
if (strlen(opt->val) > 3 && !memcmp(opt->val, "re:", 3))
load_vlan_mon_re(opt->val, mask, sizeof(mask));
else
- add_vlan_mon(opt->val, mask, sizeof(mask));
+ add_vlan_mon(opt->val, mask);
}
}
diff --git a/drivers/ipoe/ipoe.c b/drivers/ipoe/ipoe.c
index fc944a8e..447b48b9 100644
--- a/drivers/ipoe/ipoe.c
+++ b/drivers/ipoe/ipoe.c
@@ -106,6 +106,7 @@ struct vlan_dev {
struct list_head entry;
int ifindex;
+ spinlock_t lock;
unsigned long vid[4096/8/sizeof(long)];
};
@@ -865,16 +866,19 @@ static int vlan_pt_recv(struct sk_buff *skb, struct net_device *dev, struct pack
if (d->ifindex == dev->ifindex)
goto found;
}
- rcu_read_lock();
+ rcu_read_unlock();
goto out;
found:
//pr_info("found %i\n", d->ifindex);
- if (d->vid[vid / (8*sizeof(long))] & (1 << (vid % (8*sizeof(long)))))
+ if (d->vid[vid / (8*sizeof(long))] & (1lu << (vid % (8*sizeof(long)))))
vid = -1;
- else
- d->vid[vid / (8*sizeof(long))] |= 1 << (vid % (8*sizeof(long)));
- rcu_read_lock();
+ else {
+ spin_lock(&d->lock);
+ d->vid[vid / (8*sizeof(long))] |= 1lu << (vid % (8*sizeof(long)));
+ spin_unlock(&d->lock);
+ }
+ rcu_read_unlock();
if (vid == -1)
goto out;
@@ -908,6 +912,8 @@ static void vlan_do_notify(struct work_struct *w)
int id = 1;
unsigned long flags;
+ //pr_info("vlan_do_notify\n");
+
while (1) {
spin_lock_irqsave(&vlan_lock, flags);
if (list_empty(&vlan_notifies))
@@ -926,10 +932,12 @@ static void vlan_do_notify(struct work_struct *w)
header = genlmsg_put(report_skb, 0, ipoe_nl_mcg.id, &ipoe_nl_family, 0, IPOE_VLAN_NOTIFY);
}
+ //pr_info("notify %i vlan %i\n", id, n->vid);
+
ns = nla_nest_start(report_skb, id++);
if (!ns)
goto nl_err;
-
+
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,32)
if (nla_put_u32(report_skb, IPOE_ATTR_IFINDEX, n->ifindex))
#else
@@ -1628,20 +1636,22 @@ static int ipoe_nl_cmd_add_vlan_mon(struct sk_buff *skb, struct genl_info *info)
}
d->ifindex = ifindex;
+ spin_lock_init(&d->lock);
if (info->attrs[IPOE_ATTR_VLAN_MASK]) {
memcpy(d->vid, nla_data(info->attrs[IPOE_ATTR_VLAN_MASK]), min((int)nla_len(info->attrs[IPOE_ATTR_VLAN_MASK]), (int)sizeof(d->vid)));
+
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
if (dev->features & NETIF_F_HW_VLAN_FILTER) {
for (i = 1; i < 4096; i++) {
- if (!(d->vid[i / (8*sizeof(long))] & (1 << (i % (8*sizeof(long))))))
+ if (!(d->vid[i / (8*sizeof(long))] & (1lu << (i % (8*sizeof(long))))))
dev->netdev_ops->ndo_vlan_rx_add_vid(dev, i);
}
}
#else
if (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER) {
for (i = 1; i < 4096; i++) {
- if (!(d->vid[i / (8*sizeof(long))] & (1 << (i % (8*sizeof(long))))))
+ if (!(d->vid[i / (8*sizeof(long))] & (1lu << (i % (8*sizeof(long))))))
dev->netdev_ops->ndo_vlan_rx_add_vid(dev, htons(ETH_P_8021Q), i);
}
}
@@ -1662,6 +1672,7 @@ static int ipoe_nl_cmd_add_vlan_mon_vid(struct sk_buff *skb, struct genl_info *i
struct vlan_dev *d;
int ifindex, vid;
struct net_device *dev;
+ unsigned long flags;
if (!info->attrs[IPOE_ATTR_IFINDEX] || !info->attrs[IPOE_ATTR_ADDR])
return -EINVAL;
@@ -1683,7 +1694,9 @@ static int ipoe_nl_cmd_add_vlan_mon_vid(struct sk_buff *skb, struct genl_info *i
down(&ipoe_wlock);
list_for_each_entry(d, &vlan_devices, entry) {
if (d->ifindex == ifindex) {
- d->vid[vid / (8*sizeof(long))] &= ~(1 << (vid % (8*sizeof(long))));
+ spin_lock_irqsave(&d->lock, flags);
+ d->vid[vid / (8*sizeof(long))] &= ~(1lu << (vid % (8*sizeof(long))));
+ spin_unlock_irqrestore(&d->lock, flags);
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
if (dev->features & NETIF_F_HW_VLAN_FILTER)
dev->netdev_ops->ndo_vlan_rx_add_vid(dev, vid);