提交 5f8334da 编写于 作者: D Dmitry Kozlov

ipoe: various bug fixes

上级 b7f37740
......@@ -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)
......
......@@ -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);
}
}
......
......@@ -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);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册