Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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.

Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Julian Anastasov <ja@ssi.bg>
Signed-off-by: Simon Horman <horms@verge.net.au>

authored by

Julian Anastasov and committed by
Simon Horman
e4ff6751 e0b26cc9

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