History

ipvs: add sync_maxlen parameter for the sync daemon

Allow setups with large MTU to send large sync packets by adding sync_maxlen parameter. The default value is now based on MTU but no more than 1500 for compatibility reasons. To avoid problems if MTU changes allow fragmentation by sending packets with DF=0. Problem reported by Dan Carpenter.

Julian Anastasov committed 11 years ago

Commit e4ff6751 parent e0b26cc4 files · +108 −102Browse files

Unified · Split

4 files
  1. include/net/ip_vs.h +11 −8
  2. include/uapi/linux/ip_vs.h +1 −0
  3. net/netfilter/ipvs/ip_vs_ctl.c +33 −20
  4. net/netfilter/ipvs/ip_vs_sync.c +63 −74
include/net/ip_vs.h+11−8
@@ -846,6 +846,13 @@ struct ipvs_master_sync_state { · 845 unmodified lines
846/* How much time to keep dests in trash */846/* How much time to keep dests in trash */
847#define IP_VS_DEST_TRASH_PERIOD (120 * HZ)847#define IP_VS_DEST_TRASH_PERIOD (120 * HZ)
848 848
849struct ipvs_sync_daemon_cfg {
850 int syncid;
851 u16 sync_maxlen;
852 /* multicast interface name */
853 char mcast_ifn[IP_VS_IFNAME_MAXLEN];
854};
855
849/* IPVS in network namespace */856/* IPVS in network namespace */
850struct netns_ipvs {857struct netns_ipvs {
851 int gen; /* Generation */858 int gen; /* Generation */
@@ -961,15 +968,10 @@ struct netns_ipvs { · 109 unmodified lines
961 spinlock_t sync_buff_lock;968 spinlock_t sync_buff_lock;
962 struct task_struct **backup_threads;969 struct task_struct **backup_threads;
963 int threads_mask;970 int threads_mask;
964 int send_mesg_maxlen;
965 int recv_mesg_maxlen;
966 volatile int sync_state;971 volatile int sync_state;
967 volatile int master_syncid;
968 volatile int backup_syncid;
969 struct mutex sync_mutex;972 struct mutex sync_mutex;
970 /* multicast interface name */973 struct ipvs_sync_daemon_cfg mcfg; /* Master Configuration */
971 char master_mcast_ifn[IP_VS_IFNAME_MAXLEN];974 struct ipvs_sync_daemon_cfg bcfg; /* Backup Configuration */
972 char backup_mcast_ifn[IP_VS_IFNAME_MAXLEN];
973 /* net name space ptr */975 /* net name space ptr */
974 struct net *net; /* Needed by timer routines */976 struct net *net; /* Needed by timer routines */
975 /* Number of heterogeneous destinations, needed becaus heterogeneous977 /* Number of heterogeneous destinations, needed becaus heterogeneous
@@ -1408,7 +1410,8 @@ static inline void ip_vs_dest_put_and_free(struct ip_vs_dest *dest) · 432 unmodified lines
1408/* IPVS sync daemon data and function prototypes1410/* IPVS sync daemon data and function prototypes
1409 * (from ip_vs_sync.c)1411 * (from ip_vs_sync.c)
1410 */1412 */
1411int start_sync_thread(struct net *net, int state, char *mcast_ifn, __u8 syncid);1413int start_sync_thread(struct net *net, struct ipvs_sync_daemon_cfg *cfg,
1414 int state);
1412int stop_sync_thread(struct net *net, int state);1415int stop_sync_thread(struct net *net, int state);
1413void ip_vs_sync_conn(struct net *net, struct ip_vs_conn *cp, int pkts);1416void ip_vs_sync_conn(struct net *net, struct ip_vs_conn *cp, int pkts);
1414 1417
include/uapi/linux/ip_vs.h+1−0
@@ -406,6 +406,7 @@ enum { · 405 unmodified lines
406 IPVS_DAEMON_ATTR_STATE, /* sync daemon state (master/backup) */406 IPVS_DAEMON_ATTR_STATE, /* sync daemon state (master/backup) */
407 IPVS_DAEMON_ATTR_MCAST_IFN, /* multicast interface name */407 IPVS_DAEMON_ATTR_MCAST_IFN, /* multicast interface name */
408 IPVS_DAEMON_ATTR_SYNC_ID, /* SyncID we belong to */408 IPVS_DAEMON_ATTR_SYNC_ID, /* SyncID we belong to */
409 IPVS_DAEMON_ATTR_SYNC_MAXLEN, /* UDP Payload Size */
409 __IPVS_DAEMON_ATTR_MAX,410 __IPVS_DAEMON_ATTR_MAX,
410};411};
411 412
net/netfilter/ipvs/ip_vs_ctl.c+33−20
@@ -2336,10 +2336,15 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len) · 2335 unmodified lines
2336 struct ip_vs_daemon_user *dm = (struct ip_vs_daemon_user *)arg;2336 struct ip_vs_daemon_user *dm = (struct ip_vs_daemon_user *)arg;
2337 2337
2338 if (cmd == IP_VS_SO_SET_STARTDAEMON) {2338 if (cmd == IP_VS_SO_SET_STARTDAEMON) {
2339 struct ipvs_sync_daemon_cfg cfg;
2340
2341 memset(&cfg, 0, sizeof(cfg));
2342 strlcpy(cfg.mcast_ifn, dm->mcast_ifn,
2343 sizeof(cfg.mcast_ifn));
2344 cfg.syncid = dm->syncid;
2339 rtnl_lock();2345 rtnl_lock();
2340 mutex_lock(&ipvs->sync_mutex);2346 mutex_lock(&ipvs->sync_mutex);
2341 ret = start_sync_thread(net, dm->state, dm->mcast_ifn,2347 ret = start_sync_thread(net, &cfg, dm->state);
2342 dm->syncid);
2343 mutex_unlock(&ipvs->sync_mutex);2348 mutex_unlock(&ipvs->sync_mutex);
2344 rtnl_unlock();2349 rtnl_unlock();
2345 } else {2350 } else {
@@ -2650,15 +2655,15 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) · 304 unmodified lines
2650 mutex_lock(&ipvs->sync_mutex);2655 mutex_lock(&ipvs->sync_mutex);
2651 if (ipvs->sync_state & IP_VS_STATE_MASTER) {2656 if (ipvs->sync_state & IP_VS_STATE_MASTER) {
2652 d[0].state = IP_VS_STATE_MASTER;2657 d[0].state = IP_VS_STATE_MASTER;
2653 strlcpy(d[0].mcast_ifn, ipvs->master_mcast_ifn,2658 strlcpy(d[0].mcast_ifn, ipvs->mcfg.mcast_ifn,
2654 sizeof(d[0].mcast_ifn));2659 sizeof(d[0].mcast_ifn));
2655 d[0].syncid = ipvs->master_syncid;2660 d[0].syncid = ipvs->mcfg.syncid;
2656 }2661 }
2657 if (ipvs->sync_state & IP_VS_STATE_BACKUP) {2662 if (ipvs->sync_state & IP_VS_STATE_BACKUP) {
2658 d[1].state = IP_VS_STATE_BACKUP;2663 d[1].state = IP_VS_STATE_BACKUP;
2659 strlcpy(d[1].mcast_ifn, ipvs->backup_mcast_ifn,2664 strlcpy(d[1].mcast_ifn, ipvs->bcfg.mcast_ifn,
2660 sizeof(d[1].mcast_ifn));2665 sizeof(d[1].mcast_ifn));
2661 d[1].syncid = ipvs->backup_syncid;2666 d[1].syncid = ipvs->bcfg.syncid;
2662 }2667 }
2663 if (copy_to_user(user, &d, sizeof(d)) != 0)2668 if (copy_to_user(user, &d, sizeof(d)) != 0)
2664 ret = -EFAULT;2669 ret = -EFAULT;
@@ -2813,6 +2818,7 @@ static const struct nla_policy ip_vs_daemon_policy[IPVS_DAEMON_ATTR_MAX + 1] = { · 148 unmodified lines
2813 [IPVS_DAEMON_ATTR_MCAST_IFN] = { .type = NLA_NUL_STRING,2818 [IPVS_DAEMON_ATTR_MCAST_IFN] = { .type = NLA_NUL_STRING,
2814 .len = IP_VS_IFNAME_MAXLEN },2819 .len = IP_VS_IFNAME_MAXLEN },
2815 [IPVS_DAEMON_ATTR_SYNC_ID] = { .type = NLA_U32 },2820 [IPVS_DAEMON_ATTR_SYNC_ID] = { .type = NLA_U32 },
2821 [IPVS_DAEMON_ATTR_SYNC_MAXLEN] = { .type = NLA_U16 },
2816};2822};
2817 2823
2818/* Policy used for attributes in nested attribute IPVS_CMD_ATTR_SERVICE */2824/* Policy used for attributes in nested attribute IPVS_CMD_ATTR_SERVICE */
@@ -3271,7 +3277,7 @@ static int ip_vs_genl_parse_dest(struct ip_vs_dest_user_kern *udest, · 452 unmodified lines
3271}3277}
3272 3278
3273static int ip_vs_genl_fill_daemon(struct sk_buff *skb, __u32 state,3279static int ip_vs_genl_fill_daemon(struct sk_buff *skb, __u32 state,
3274 const char *mcast_ifn, __u32 syncid)3280 struct ipvs_sync_daemon_cfg *c)
3275{3281{
3276 struct nlattr *nl_daemon;3282 struct nlattr *nl_daemon;
3277 3283
@@ -3280,8 +3286,9 @@ static int ip_vs_genl_fill_daemon(struct sk_buff *skb, __u32 state, · 2 unmodified lines
3280 return -EMSGSIZE;3286 return -EMSGSIZE;
3281 3287
3282 if (nla_put_u32(skb, IPVS_DAEMON_ATTR_STATE, state) ||3288 if (nla_put_u32(skb, IPVS_DAEMON_ATTR_STATE, state) ||
3283 nla_put_string(skb, IPVS_DAEMON_ATTR_MCAST_IFN, mcast_ifn) ||3289 nla_put_string(skb, IPVS_DAEMON_ATTR_MCAST_IFN, c->mcast_ifn) ||
3284 nla_put_u32(skb, IPVS_DAEMON_ATTR_SYNC_ID, syncid))3290 nla_put_u32(skb, IPVS_DAEMON_ATTR_SYNC_ID, c->syncid) ||
3291 nla_put_u16(skb, IPVS_DAEMON_ATTR_SYNC_MAXLEN, c->sync_maxlen))
3285 goto nla_put_failure;3292 goto nla_put_failure;
3286 nla_nest_end(skb, nl_daemon);3293 nla_nest_end(skb, nl_daemon);
3287 3294
@@ -3293,7 +3300,7 @@ nla_put_failure: · 5 unmodified lines
3293}3300}
3294 3301
3295static int ip_vs_genl_dump_daemon(struct sk_buff *skb, __u32 state,3302static int ip_vs_genl_dump_daemon(struct sk_buff *skb, __u32 state,
3296 const char *mcast_ifn, __u32 syncid,3303 struct ipvs_sync_daemon_cfg *c,
3297 struct netlink_callback *cb)3304 struct netlink_callback *cb)
3298{3305{
3299 void *hdr;3306 void *hdr;
@@ -3303,7 +3310,7 @@ static int ip_vs_genl_dump_daemon(struct sk_buff *skb, __u32 state, · 3 unmodified lines
3303 if (!hdr)3310 if (!hdr)
3304 return -EMSGSIZE;3311 return -EMSGSIZE;
3305 3312
3306 if (ip_vs_genl_fill_daemon(skb, state, mcast_ifn, syncid))3313 if (ip_vs_genl_fill_daemon(skb, state, c))
3307 goto nla_put_failure;3314 goto nla_put_failure;
3308 3315
3309 genlmsg_end(skb, hdr);3316 genlmsg_end(skb, hdr);
@@ -3323,8 +3330,7 @@ static int ip_vs_genl_dump_daemons(struct sk_buff *skb, · 13 unmodified lines
3323 mutex_lock(&ipvs->sync_mutex);3330 mutex_lock(&ipvs->sync_mutex);
3324 if ((ipvs->sync_state & IP_VS_STATE_MASTER) && !cb->args[0]) {3331 if ((ipvs->sync_state & IP_VS_STATE_MASTER) && !cb->args[0]) {
3325 if (ip_vs_genl_dump_daemon(skb, IP_VS_STATE_MASTER,3332 if (ip_vs_genl_dump_daemon(skb, IP_VS_STATE_MASTER,
3326 ipvs->master_mcast_ifn,3333 &ipvs->mcfg, cb) < 0)
3327 ipvs->master_syncid, cb) < 0)
3328 goto nla_put_failure;3334 goto nla_put_failure;
3329 3335
3330 cb->args[0] = 1;3336 cb->args[0] = 1;
@@ -3332,8 +3338,7 @@ static int ip_vs_genl_dump_daemons(struct sk_buff *skb, · 1 unmodified line
3332 3338
3333 if ((ipvs->sync_state & IP_VS_STATE_BACKUP) && !cb->args[1]) {3339 if ((ipvs->sync_state & IP_VS_STATE_BACKUP) && !cb->args[1]) {
3334 if (ip_vs_genl_dump_daemon(skb, IP_VS_STATE_BACKUP,3340 if (ip_vs_genl_dump_daemon(skb, IP_VS_STATE_BACKUP,
3335 ipvs->backup_mcast_ifn,3341 &ipvs->bcfg, cb) < 0)
3336 ipvs->backup_syncid, cb) < 0)
3337 goto nla_put_failure;3342 goto nla_put_failure;
3338 3343
3339 cb->args[1] = 1;3344 cb->args[1] = 1;
@@ -3348,25 +3353,33 @@ nla_put_failure: · 8 unmodified lines
3348static int ip_vs_genl_new_daemon(struct net *net, struct nlattr **attrs)3353static int ip_vs_genl_new_daemon(struct net *net, struct nlattr **attrs)
3349{3354{
3350 struct netns_ipvs *ipvs = net_ipvs(net);3355 struct netns_ipvs *ipvs = net_ipvs(net);
3356 struct ipvs_sync_daemon_cfg c;
3357 struct nlattr *a;
3351 int ret;3358 int ret;
3352 3359
3360 memset(&c, 0, sizeof(c));
3353 if (!(attrs[IPVS_DAEMON_ATTR_STATE] &&3361 if (!(attrs[IPVS_DAEMON_ATTR_STATE] &&
3354 attrs[IPVS_DAEMON_ATTR_MCAST_IFN] &&3362 attrs[IPVS_DAEMON_ATTR_MCAST_IFN] &&
3355 attrs[IPVS_DAEMON_ATTR_SYNC_ID]))3363 attrs[IPVS_DAEMON_ATTR_SYNC_ID]))
3356 return -EINVAL;3364 return -EINVAL;
3365 strlcpy(c.mcast_ifn, nla_data(attrs[IPVS_DAEMON_ATTR_MCAST_IFN]),
3366 sizeof(c.mcast_ifn));
3367 c.syncid = nla_get_u32(attrs[IPVS_DAEMON_ATTR_SYNC_ID]);
3368
3369 a = attrs[IPVS_DAEMON_ATTR_SYNC_MAXLEN];
3370 if (a)
3371 c.sync_maxlen = nla_get_u16(a);
3357 3372
3358 /* The synchronization protocol is incompatible with mixed family3373 /* The synchronization protocol is incompatible with mixed family
3359 * services3374 * services
3360 */3375 */
3361 if (net_ipvs(net)->mixed_address_family_dests > 0)3376 if (ipvs->mixed_address_family_dests > 0)
3362 return -EINVAL;3377 return -EINVAL;
3363 3378
3364 rtnl_lock();3379 rtnl_lock();
3365 mutex_lock(&ipvs->sync_mutex);3380 mutex_lock(&ipvs->sync_mutex);
3366 ret = start_sync_thread(net,3381 ret = start_sync_thread(net, &c,
3367 nla_get_u32(attrs[IPVS_DAEMON_ATTR_STATE]),3382 nla_get_u32(attrs[IPVS_DAEMON_ATTR_STATE]));
3368 nla_data(attrs[IPVS_DAEMON_ATTR_MCAST_IFN]),
3369 nla_get_u32(attrs[IPVS_DAEMON_ATTR_SYNC_ID]));
3370 mutex_unlock(&ipvs->sync_mutex);3383 mutex_unlock(&ipvs->sync_mutex);
3371 rtnl_unlock();3384 rtnl_unlock();
3372 return ret;3385 return ret;
net/netfilter/ipvs/ip_vs_sync.c+63−74
@@ -320,26 +320,28 @@ sb_dequeue(struct netns_ipvs *ipvs, struct ipvs_master_sync_state *ms) · 319 unmodified lines
320 * Create a new sync buffer for Version 1 proto.320 * Create a new sync buffer for Version 1 proto.
321 */321 */
322static inline struct ip_vs_sync_buff *322static inline struct ip_vs_sync_buff *
323ip_vs_sync_buff_create(struct netns_ipvs *ipvs)323ip_vs_sync_buff_create(struct netns_ipvs *ipvs, unsigned int len)
324{324{
325 struct ip_vs_sync_buff *sb;325 struct ip_vs_sync_buff *sb;
326 326
327 if (!(sb=kmalloc(sizeof(struct ip_vs_sync_buff), GFP_ATOMIC)))327 if (!(sb=kmalloc(sizeof(struct ip_vs_sync_buff), GFP_ATOMIC)))
328 return NULL;328 return NULL;
329 329
330 sb->mesg = kmalloc(ipvs->send_mesg_maxlen, GFP_ATOMIC);330 len = max_t(unsigned int, len + sizeof(struct ip_vs_sync_mesg),
331 ipvs->mcfg.sync_maxlen);
332 sb->mesg = kmalloc(len, GFP_ATOMIC);
331 if (!sb->mesg) {333 if (!sb->mesg) {
332 kfree(sb);334 kfree(sb);
333 return NULL;335 return NULL;
334 }336 }
335 sb->mesg->reserved = 0; /* old nr_conns i.e. must be zero now */337 sb->mesg->reserved = 0; /* old nr_conns i.e. must be zero now */
336 sb->mesg->version = SYNC_PROTO_VER;338 sb->mesg->version = SYNC_PROTO_VER;
337 sb->mesg->syncid = ipvs->master_syncid;339 sb->mesg->syncid = ipvs->mcfg.syncid;
338 sb->mesg->size = htons(sizeof(struct ip_vs_sync_mesg));340 sb->mesg->size = htons(sizeof(struct ip_vs_sync_mesg));
339 sb->mesg->nr_conns = 0;341 sb->mesg->nr_conns = 0;
340 sb->mesg->spare = 0;342 sb->mesg->spare = 0;
341 sb->head = (unsigned char *)sb->mesg + sizeof(struct ip_vs_sync_mesg);343 sb->head = (unsigned char *)sb->mesg + sizeof(struct ip_vs_sync_mesg);
342 sb->end = (unsigned char *)sb->mesg + ipvs->send_mesg_maxlen;344 sb->end = (unsigned char *)sb->mesg + len;
343 345
344 sb->firstuse = jiffies;346 sb->firstuse = jiffies;
345 return sb;347 return sb;
@@ -402,7 +404,7 @@ select_master_thread_id(struct netns_ipvs *ipvs, struct ip_vs_conn *cp) · 56 unmodified lines
402 * Create a new sync buffer for Version 0 proto.404 * Create a new sync buffer for Version 0 proto.
403 */405 */
404static inline struct ip_vs_sync_buff *406static inline struct ip_vs_sync_buff *
405ip_vs_sync_buff_create_v0(struct netns_ipvs *ipvs)407ip_vs_sync_buff_create_v0(struct netns_ipvs *ipvs, unsigned int len)
406{408{
407 struct ip_vs_sync_buff *sb;409 struct ip_vs_sync_buff *sb;
408 struct ip_vs_sync_mesg_v0 *mesg;410 struct ip_vs_sync_mesg_v0 *mesg;
@@ -410,17 +412,19 @@ ip_vs_sync_buff_create_v0(struct netns_ipvs *ipvs) · 1 unmodified line
410 if (!(sb=kmalloc(sizeof(struct ip_vs_sync_buff), GFP_ATOMIC)))412 if (!(sb=kmalloc(sizeof(struct ip_vs_sync_buff), GFP_ATOMIC)))
411 return NULL;413 return NULL;
412 414
413 sb->mesg = kmalloc(ipvs->send_mesg_maxlen, GFP_ATOMIC);415 len = max_t(unsigned int, len + sizeof(struct ip_vs_sync_mesg_v0),
416 ipvs->mcfg.sync_maxlen);
417 sb->mesg = kmalloc(len, GFP_ATOMIC);
414 if (!sb->mesg) {418 if (!sb->mesg) {
415 kfree(sb);419 kfree(sb);
416 return NULL;420 return NULL;
417 }421 }
418 mesg = (struct ip_vs_sync_mesg_v0 *)sb->mesg;422 mesg = (struct ip_vs_sync_mesg_v0 *)sb->mesg;
419 mesg->nr_conns = 0;423 mesg->nr_conns = 0;
420 mesg->syncid = ipvs->master_syncid;424 mesg->syncid = ipvs->mcfg.syncid;
421 mesg->size = htons(sizeof(struct ip_vs_sync_mesg_v0));425 mesg->size = htons(sizeof(struct ip_vs_sync_mesg_v0));
422 sb->head = (unsigned char *)mesg + sizeof(struct ip_vs_sync_mesg_v0);426 sb->head = (unsigned char *)mesg + sizeof(struct ip_vs_sync_mesg_v0);
423 sb->end = (unsigned char *)mesg + ipvs->send_mesg_maxlen;427 sb->end = (unsigned char *)mesg + len;
424 sb->firstuse = jiffies;428 sb->firstuse = jiffies;
425 return sb;429 return sb;
426}430}
@@ -533,7 +537,7 @@ static void ip_vs_sync_conn_v0(struct net *net, struct ip_vs_conn *cp, · 106 unmodified lines
533 struct ip_vs_sync_buff *buff;537 struct ip_vs_sync_buff *buff;
534 struct ipvs_master_sync_state *ms;538 struct ipvs_master_sync_state *ms;
535 int id;539 int id;
536 int len;540 unsigned int len;
537 541
538 if (unlikely(cp->af != AF_INET))542 if (unlikely(cp->af != AF_INET))
539 return;543 return;
@@ -553,17 +557,19 @@ static void ip_vs_sync_conn_v0(struct net *net, struct ip_vs_conn *cp, · 13 unmodified lines
553 id = select_master_thread_id(ipvs, cp);557 id = select_master_thread_id(ipvs, cp);
554 ms = &ipvs->ms[id];558 ms = &ipvs->ms[id];
555 buff = ms->sync_buff;559 buff = ms->sync_buff;
560 len = (cp->flags & IP_VS_CONN_F_SEQ_MASK) ? FULL_CONN_SIZE :
561 SIMPLE_CONN_SIZE;
556 if (buff) {562 if (buff) {
557 m = (struct ip_vs_sync_mesg_v0 *) buff->mesg;563 m = (struct ip_vs_sync_mesg_v0 *) buff->mesg;
558 /* Send buffer if it is for v1 */564 /* Send buffer if it is for v1 */
559 if (!m->nr_conns) {565 if (buff->head + len > buff->end || !m->nr_conns) {
560 sb_queue_tail(ipvs, ms);566 sb_queue_tail(ipvs, ms);
561 ms->sync_buff = NULL;567 ms->sync_buff = NULL;
562 buff = NULL;568 buff = NULL;
563 }569 }
564 }570 }
565 if (!buff) {571 if (!buff) {
566 buff = ip_vs_sync_buff_create_v0(ipvs);572 buff = ip_vs_sync_buff_create_v0(ipvs, len);
567 if (!buff) {573 if (!buff) {
568 spin_unlock_bh(&ipvs->sync_buff_lock);574 spin_unlock_bh(&ipvs->sync_buff_lock);
569 pr_err("ip_vs_sync_buff_create failed.\n");575 pr_err("ip_vs_sync_buff_create failed.\n");
@@ -572,8 +578,6 @@ static void ip_vs_sync_conn_v0(struct net *net, struct ip_vs_conn *cp, · 2 unmodified lines
572 ms->sync_buff = buff;578 ms->sync_buff = buff;
573 }579 }
574 580
575 len = (cp->flags & IP_VS_CONN_F_SEQ_MASK) ? FULL_CONN_SIZE :
576 SIMPLE_CONN_SIZE;
577 m = (struct ip_vs_sync_mesg_v0 *) buff->mesg;581 m = (struct ip_vs_sync_mesg_v0 *) buff->mesg;
578 s = (struct ip_vs_sync_conn_v0 *) buff->head;582 s = (struct ip_vs_sync_conn_v0 *) buff->head;
579 583
@@ -597,12 +601,6 @@ static void ip_vs_sync_conn_v0(struct net *net, struct ip_vs_conn *cp, · 17 unmodified lines
597 m->nr_conns++;601 m->nr_conns++;
598 m->size = htons(ntohs(m->size) + len);602 m->size = htons(ntohs(m->size) + len);
599 buff->head += len;603 buff->head += len;
600
601 /* check if there is a space for next one */
602 if (buff->head + FULL_CONN_SIZE > buff->end) {
603 sb_queue_tail(ipvs, ms);
604 ms->sync_buff = NULL;
605 }
606 spin_unlock_bh(&ipvs->sync_buff_lock);604 spin_unlock_bh(&ipvs->sync_buff_lock);
607 605
608 /* synchronize its controller if it has */606 /* synchronize its controller if it has */
@@ -694,7 +692,7 @@ sloop: · 85 unmodified lines
694 }692 }
695 693
696 if (!buff) {694 if (!buff) {
697 buff = ip_vs_sync_buff_create(ipvs);695 buff = ip_vs_sync_buff_create(ipvs, len);
698 if (!buff) {696 if (!buff) {
699 spin_unlock_bh(&ipvs->sync_buff_lock);697 spin_unlock_bh(&ipvs->sync_buff_lock);
700 pr_err("ip_vs_sync_buff_create failed.\n");698 pr_err("ip_vs_sync_buff_create failed.\n");
@@ -1219,7 +1217,7 @@ static void ip_vs_process_message(struct net *net, __u8 *buffer, · 518 unmodified lines
1219 return;1217 return;
1220 }1218 }
1221 /* SyncID sanity check */1219 /* SyncID sanity check */
1222 if (ipvs->backup_syncid != 0 && m2->syncid != ipvs->backup_syncid) {1220 if (ipvs->bcfg.syncid != 0 && m2->syncid != ipvs->bcfg.syncid) {
1223 IP_VS_DBG(7, "BACKUP, Ignoring syncid = %d\n", m2->syncid);1221 IP_VS_DBG(7, "BACKUP, Ignoring syncid = %d\n", m2->syncid);
1224 return;1222 return;
1225 }1223 }
@@ -1319,6 +1317,17 @@ static void set_mcast_ttl(struct sock *sk, u_char ttl) · 93 unmodified lines
1319 release_sock(sk);1317 release_sock(sk);
1320}1318}
1321 1319
1320/* Control fragmentation of messages */
1321static void set_mcast_pmtudisc(struct sock *sk, int val)
1322{
1323 struct inet_sock *inet = inet_sk(sk);
1324
1325 /* setsockopt(sock, SOL_IP, IP_MTU_DISCOVER, &val, sizeof(val)); */
1326 lock_sock(sk);
1327 inet->pmtudisc = val;
1328 release_sock(sk);
1329}
1330
1322/*1331/*
1323 * Specifiy default interface for outgoing multicasts1332 * Specifiy default interface for outgoing multicasts
1324 */1333 */
@@ -1344,43 +1353,6 @@ static int set_mcast_if(struct sock *sk, char *ifname) · 19 unmodified lines
1344}1353}
1345 1354
1346 1355
1347/*
1348 * Set the maximum length of sync message according to the
1349 * specified interface's MTU.
1350 */
1351static int set_sync_mesg_maxlen(struct net *net, int sync_state)
1352{
1353 struct netns_ipvs *ipvs = net_ipvs(net);
1354 struct net_device *dev;
1355 int num;
1356
1357 if (sync_state == IP_VS_STATE_MASTER) {
1358 dev = __dev_get_by_name(net, ipvs->master_mcast_ifn);
1359 if (!dev)
1360 return -ENODEV;
1361
1362 num = (dev->mtu - sizeof(struct iphdr) -
1363 sizeof(struct udphdr) -
1364 SYNC_MESG_HEADER_LEN - 20) / SIMPLE_CONN_SIZE;
1365 ipvs->send_mesg_maxlen = SYNC_MESG_HEADER_LEN +
1366 SIMPLE_CONN_SIZE * min(num, MAX_CONNS_PER_SYNCBUFF);
1367 IP_VS_DBG(7, "setting the maximum length of sync sending "
1368 "message %d.\n", ipvs->send_mesg_maxlen);
1369 } else if (sync_state == IP_VS_STATE_BACKUP) {
1370 dev = __dev_get_by_name(net, ipvs->backup_mcast_ifn);
1371 if (!dev)
1372 return -ENODEV;
1373
1374 ipvs->recv_mesg_maxlen = dev->mtu -
1375 sizeof(struct iphdr) - sizeof(struct udphdr);
1376 IP_VS_DBG(7, "setting the maximum length of sync receiving "
1377 "message %d.\n", ipvs->recv_mesg_maxlen);
1378 }
1379
1380 return 0;
1381}
1382
1383
1384/*1356/*
1385 * Join a multicast group.1357 * Join a multicast group.
1386 * the group is specified by a class D multicast address 224.0.0.0/81358 * the group is specified by a class D multicast address 224.0.0.0/8
@@ -1461,7 +1433,7 @@ static struct socket *make_send_sock(struct net *net, int id) · 74 unmodified lines
1461 pr_err("Error during creation of socket; terminating\n");1433 pr_err("Error during creation of socket; terminating\n");
1462 return ERR_PTR(result);1434 return ERR_PTR(result);
1463 }1435 }
1464 result = set_mcast_if(sock->sk, ipvs->master_mcast_ifn);1436 result = set_mcast_if(sock->sk, ipvs->mcfg.mcast_ifn);
1465 if (result < 0) {1437 if (result < 0) {
1466 pr_err("Error setting outbound mcast interface\n");1438 pr_err("Error setting outbound mcast interface\n");
1467 goto error;1439 goto error;
@@ -1469,11 +1441,13 @@ static struct socket *make_send_sock(struct net *net, int id) · 1 unmodified line
1469 1441
1470 set_mcast_loop(sock->sk, 0);1442 set_mcast_loop(sock->sk, 0);
1471 set_mcast_ttl(sock->sk, 1);1443 set_mcast_ttl(sock->sk, 1);
1444 /* Allow fragmentation if MTU changes */
1445 set_mcast_pmtudisc(sock->sk, IP_PMTUDISC_DONT);
1472 result = sysctl_sync_sock_size(ipvs);1446 result = sysctl_sync_sock_size(ipvs);
1473 if (result > 0)1447 if (result > 0)
1474 set_sock_size(sock->sk, 1, result);1448 set_sock_size(sock->sk, 1, result);
1475 1449
1476 result = bind_mcastif_addr(sock, ipvs->master_mcast_ifn);1450 result = bind_mcastif_addr(sock, ipvs->mcfg.mcast_ifn);
1477 if (result < 0) {1451 if (result < 0) {
1478 pr_err("Error binding address of the mcast interface\n");1452 pr_err("Error binding address of the mcast interface\n");
1479 goto error;1453 goto error;
@@ -1531,7 +1505,7 @@ static struct socket *make_receive_sock(struct net *net, int id) · 51 unmodified lines
1531 /* join the multicast group */1505 /* join the multicast group */
1532 result = join_mcast_group(sock->sk,1506 result = join_mcast_group(sock->sk,
1533 (struct in_addr *) &mcast_addr.sin_addr,1507 (struct in_addr *) &mcast_addr.sin_addr,
1534 ipvs->backup_mcast_ifn);1508 ipvs->bcfg.mcast_ifn);
1535 if (result < 0) {1509 if (result < 0) {
1536 pr_err("Error joining to the multicast group\n");1510 pr_err("Error joining to the multicast group\n");
1537 goto error;1511 goto error;
@@ -1639,7 +1613,7 @@ static int sync_thread_master(void *data) · 101 unmodified lines
1639 1613
1640 pr_info("sync thread started: state = MASTER, mcast_ifn = %s, "1614 pr_info("sync thread started: state = MASTER, mcast_ifn = %s, "
1641 "syncid = %d, id = %d\n",1615 "syncid = %d, id = %d\n",
1642 ipvs->master_mcast_ifn, ipvs->master_syncid, tinfo->id);1616 ipvs->mcfg.mcast_ifn, ipvs->mcfg.syncid, tinfo->id);
1643 1617
1644 for (;;) {1618 for (;;) {
1645 sb = next_sync_buff(ipvs, ms);1619 sb = next_sync_buff(ipvs, ms);
@@ -1693,7 +1667,7 @@ static int sync_thread_backup(void *data) · 47 unmodified lines
1693 1667
1694 pr_info("sync thread started: state = BACKUP, mcast_ifn = %s, "1668 pr_info("sync thread started: state = BACKUP, mcast_ifn = %s, "
1695 "syncid = %d, id = %d\n",1669 "syncid = %d, id = %d\n",
1696 ipvs->backup_mcast_ifn, ipvs->backup_syncid, tinfo->id);1670 ipvs->bcfg.mcast_ifn, ipvs->bcfg.syncid, tinfo->id);
1697 1671
1698 while (!kthread_should_stop()) {1672 while (!kthread_should_stop()) {
1699 wait_event_interruptible(*sk_sleep(tinfo->sock->sk),1673 wait_event_interruptible(*sk_sleep(tinfo->sock->sk),
@@ -1703,7 +1677,7 @@ static int sync_thread_backup(void *data) · 3 unmodified lines
1703 /* do we have data now? */1677 /* do we have data now? */
1704 while (!skb_queue_empty(&(tinfo->sock->sk->sk_receive_queue))) {1678 while (!skb_queue_empty(&(tinfo->sock->sk->sk_receive_queue))) {
1705 len = ip_vs_receive(tinfo->sock, tinfo->buf,1679 len = ip_vs_receive(tinfo->sock, tinfo->buf,
1706 ipvs->recv_mesg_maxlen);1680 ipvs->bcfg.sync_maxlen);
1707 if (len <= 0) {1681 if (len <= 0) {
1708 if (len != -EAGAIN)1682 if (len != -EAGAIN)
1709 pr_err("receiving message error\n");1683 pr_err("receiving message error\n");
@@ -1723,16 +1697,19 @@ static int sync_thread_backup(void *data) · 13 unmodified lines
1723}1697}
1724 1698
1725 1699
1726int start_sync_thread(struct net *net, int state, char *mcast_ifn, __u8 syncid)1700int start_sync_thread(struct net *net, struct ipvs_sync_daemon_cfg *c,
1701 int state)
1727{1702{
1728 struct ip_vs_sync_thread_data *tinfo;1703 struct ip_vs_sync_thread_data *tinfo;
1729 struct task_struct **array = NULL, *task;1704 struct task_struct **array = NULL, *task;
1730 struct socket *sock;1705 struct socket *sock;
1731 struct netns_ipvs *ipvs = net_ipvs(net);1706 struct netns_ipvs *ipvs = net_ipvs(net);
1707 struct net_device *dev;
1732 char *name;1708 char *name;
1733 int (*threadfn)(void *data);1709 int (*threadfn)(void *data);
1734 int id, count;1710 int id, count, hlen;
1735 int result = -ENOMEM;1711 int result = -ENOMEM;
1712 u16 mtu, min_mtu;
1736 1713
1737 IP_VS_DBG(7, "%s(): pid %d\n", __func__, task_pid_nr(current));1714 IP_VS_DBG(7, "%s(): pid %d\n", __func__, task_pid_nr(current));
1738 IP_VS_DBG(7, "Each ip_vs_sync_conn entry needs %Zd bytes\n",1715 IP_VS_DBG(7, "Each ip_vs_sync_conn entry needs %Zd bytes\n",
@@ -1744,22 +1721,35 @@ int start_sync_thread(struct net *net, int state, char *mcast_ifn, __u8 syncid) · 5 unmodified lines
1744 } else1721 } else
1745 count = ipvs->threads_mask + 1;1722 count = ipvs->threads_mask + 1;
1746 1723
1724 dev = __dev_get_by_name(net, c->mcast_ifn);
1725 if (!dev) {
1726 pr_err("Unknown mcast interface: %s\n", c->mcast_ifn);
1727 return -ENODEV;
1728 }
1729 hlen = sizeof(struct iphdr) + sizeof(struct udphdr);
1730 mtu = (state == IP_VS_STATE_BACKUP) ?
1731 clamp(dev->mtu, 1500U, 65535U) : 1500U;
1732 min_mtu = (state == IP_VS_STATE_BACKUP) ? 1024 : 1;
1733
1734 if (c->sync_maxlen)
1735 c->sync_maxlen = clamp_t(unsigned int,
1736 c->sync_maxlen, min_mtu,
1737 65535 - hlen);
1738 else
1739 c->sync_maxlen = mtu - hlen;
1740
1747 if (state == IP_VS_STATE_MASTER) {1741 if (state == IP_VS_STATE_MASTER) {
1748 if (ipvs->ms)1742 if (ipvs->ms)
1749 return -EEXIST;1743 return -EEXIST;
1750 1744
1751 strlcpy(ipvs->master_mcast_ifn, mcast_ifn,1745 ipvs->mcfg = *c;
1752 sizeof(ipvs->master_mcast_ifn));
1753 ipvs->master_syncid = syncid;
1754 name = "ipvs-m:%d:%d";1746 name = "ipvs-m:%d:%d";
1755 threadfn = sync_thread_master;1747 threadfn = sync_thread_master;
1756 } else if (state == IP_VS_STATE_BACKUP) {1748 } else if (state == IP_VS_STATE_BACKUP) {
1757 if (ipvs->backup_threads)1749 if (ipvs->backup_threads)
1758 return -EEXIST;1750 return -EEXIST;
1759 1751
1760 strlcpy(ipvs->backup_mcast_ifn, mcast_ifn,1752 ipvs->bcfg = *c;
1761 sizeof(ipvs->backup_mcast_ifn));
1762 ipvs->backup_syncid = syncid;
1763 name = "ipvs-b:%d:%d";1753 name = "ipvs-b:%d:%d";
1764 threadfn = sync_thread_backup;1754 threadfn = sync_thread_backup;
1765 } else {1755 } else {
@@ -1787,7 +1777,6 @@ int start_sync_thread(struct net *net, int state, char *mcast_ifn, __u8 syncid) · 21 unmodified lines
1787 if (!array)1777 if (!array)
1788 goto out;1778 goto out;
1789 }1779 }
1790 set_sync_mesg_maxlen(net, state);
1791 1780
1792 tinfo = NULL;1781 tinfo = NULL;
1793 for (id = 0; id < count; id++) {1782 for (id = 0; id < count; id++) {
@@ -1805,7 +1794,7 @@ int start_sync_thread(struct net *net, int state, char *mcast_ifn, __u8 syncid) · 11 unmodified lines
1805 tinfo->net = net;1794 tinfo->net = net;
1806 tinfo->sock = sock;1795 tinfo->sock = sock;
1807 if (state == IP_VS_STATE_BACKUP) {1796 if (state == IP_VS_STATE_BACKUP) {
1808 tinfo->buf = kmalloc(ipvs->recv_mesg_maxlen,1797 tinfo->buf = kmalloc(ipvs->bcfg.sync_maxlen,
1809 GFP_KERNEL);1798 GFP_KERNEL);
1810 if (!tinfo->buf)1799 if (!tinfo->buf)
1811 goto outtinfo;1800 goto outtinfo;

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t