Skip to content

Commit e4ff675

Browse files
Julian Anastasovhorms
Julian Anastasov
authored andcommitted
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 <[email protected]> Signed-off-by: Julian Anastasov <[email protected]> Signed-off-by: Simon Horman <[email protected]>
1 parent e0b26cc commit e4ff675

File tree

4 files changed

+108
-102
lines changed

4 files changed

+108
-102
lines changed

include/net/ip_vs.h

+11-8
Original file line numberDiff line numberDiff line change
@@ -846,6 +846,13 @@ struct ipvs_master_sync_state {
846846
/* How much time to keep dests in trash */
847847
#define IP_VS_DEST_TRASH_PERIOD (120 * HZ)
848848

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+
849856
/* IPVS in network namespace */
850857
struct netns_ipvs {
851858
int gen; /* Generation */
@@ -961,15 +968,10 @@ struct netns_ipvs {
961968
spinlock_t sync_buff_lock;
962969
struct task_struct **backup_threads;
963970
int threads_mask;
964-
int send_mesg_maxlen;
965-
int recv_mesg_maxlen;
966971
volatile int sync_state;
967-
volatile int master_syncid;
968-
volatile int backup_syncid;
969972
struct mutex sync_mutex;
970-
/* multicast interface name */
971-
char master_mcast_ifn[IP_VS_IFNAME_MAXLEN];
972-
char backup_mcast_ifn[IP_VS_IFNAME_MAXLEN];
973+
struct ipvs_sync_daemon_cfg mcfg; /* Master Configuration */
974+
struct ipvs_sync_daemon_cfg bcfg; /* Backup Configuration */
973975
/* net name space ptr */
974976
struct net *net; /* Needed by timer routines */
975977
/* 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)
14081410
/* IPVS sync daemon data and function prototypes
14091411
* (from ip_vs_sync.c)
14101412
*/
1411-
int start_sync_thread(struct net *net, int state, char *mcast_ifn, __u8 syncid);
1413+
int start_sync_thread(struct net *net, struct ipvs_sync_daemon_cfg *cfg,
1414+
int state);
14121415
int stop_sync_thread(struct net *net, int state);
14131416
void ip_vs_sync_conn(struct net *net, struct ip_vs_conn *cp, int pkts);
14141417

include/uapi/linux/ip_vs.h

+1
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,7 @@ enum {
406406
IPVS_DAEMON_ATTR_STATE, /* sync daemon state (master/backup) */
407407
IPVS_DAEMON_ATTR_MCAST_IFN, /* multicast interface name */
408408
IPVS_DAEMON_ATTR_SYNC_ID, /* SyncID we belong to */
409+
IPVS_DAEMON_ATTR_SYNC_MAXLEN, /* UDP Payload Size */
409410
__IPVS_DAEMON_ATTR_MAX,
410411
};
411412

net/netfilter/ipvs/ip_vs_ctl.c

+33-20
Original file line numberDiff line numberDiff line change
@@ -2336,10 +2336,15 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
23362336
struct ip_vs_daemon_user *dm = (struct ip_vs_daemon_user *)arg;
23372337

23382338
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;
23392345
rtnl_lock();
23402346
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);
23432348
mutex_unlock(&ipvs->sync_mutex);
23442349
rtnl_unlock();
23452350
} else {
@@ -2650,15 +2655,15 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
26502655
mutex_lock(&ipvs->sync_mutex);
26512656
if (ipvs->sync_state & IP_VS_STATE_MASTER) {
26522657
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,
26542659
sizeof(d[0].mcast_ifn));
2655-
d[0].syncid = ipvs->master_syncid;
2660+
d[0].syncid = ipvs->mcfg.syncid;
26562661
}
26572662
if (ipvs->sync_state & IP_VS_STATE_BACKUP) {
26582663
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,
26602665
sizeof(d[1].mcast_ifn));
2661-
d[1].syncid = ipvs->backup_syncid;
2666+
d[1].syncid = ipvs->bcfg.syncid;
26622667
}
26632668
if (copy_to_user(user, &d, sizeof(d)) != 0)
26642669
ret = -EFAULT;
@@ -2813,6 +2818,7 @@ static const struct nla_policy ip_vs_daemon_policy[IPVS_DAEMON_ATTR_MAX + 1] = {
28132818
[IPVS_DAEMON_ATTR_MCAST_IFN] = { .type = NLA_NUL_STRING,
28142819
.len = IP_VS_IFNAME_MAXLEN },
28152820
[IPVS_DAEMON_ATTR_SYNC_ID] = { .type = NLA_U32 },
2821+
[IPVS_DAEMON_ATTR_SYNC_MAXLEN] = { .type = NLA_U16 },
28162822
};
28172823

28182824
/* 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,
32713277
}
32723278

32733279
static 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)
32753281
{
32763282
struct nlattr *nl_daemon;
32773283

@@ -3280,8 +3286,9 @@ static int ip_vs_genl_fill_daemon(struct sk_buff *skb, __u32 state,
32803286
return -EMSGSIZE;
32813287

32823288
if (nla_put_u32(skb, IPVS_DAEMON_ATTR_STATE, state) ||
3283-
nla_put_string(skb, IPVS_DAEMON_ATTR_MCAST_IFN, mcast_ifn) ||
3284-
nla_put_u32(skb, IPVS_DAEMON_ATTR_SYNC_ID, syncid))
3289+
nla_put_string(skb, IPVS_DAEMON_ATTR_MCAST_IFN, c->mcast_ifn) ||
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))
32853292
goto nla_put_failure;
32863293
nla_nest_end(skb, nl_daemon);
32873294

@@ -3293,7 +3300,7 @@ static int ip_vs_genl_fill_daemon(struct sk_buff *skb, __u32 state,
32933300
}
32943301

32953302
static 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,
32973304
struct netlink_callback *cb)
32983305
{
32993306
void *hdr;
@@ -3303,7 +3310,7 @@ static int ip_vs_genl_dump_daemon(struct sk_buff *skb, __u32 state,
33033310
if (!hdr)
33043311
return -EMSGSIZE;
33053312

3306-
if (ip_vs_genl_fill_daemon(skb, state, mcast_ifn, syncid))
3313+
if (ip_vs_genl_fill_daemon(skb, state, c))
33073314
goto nla_put_failure;
33083315

33093316
genlmsg_end(skb, hdr);
@@ -3323,17 +3330,15 @@ static int ip_vs_genl_dump_daemons(struct sk_buff *skb,
33233330
mutex_lock(&ipvs->sync_mutex);
33243331
if ((ipvs->sync_state & IP_VS_STATE_MASTER) && !cb->args[0]) {
33253332
if (ip_vs_genl_dump_daemon(skb, IP_VS_STATE_MASTER,
3326-
ipvs->master_mcast_ifn,
3327-
ipvs->master_syncid, cb) < 0)
3333+
&ipvs->mcfg, cb) < 0)
33283334
goto nla_put_failure;
33293335

33303336
cb->args[0] = 1;
33313337
}
33323338

33333339
if ((ipvs->sync_state & IP_VS_STATE_BACKUP) && !cb->args[1]) {
33343340
if (ip_vs_genl_dump_daemon(skb, IP_VS_STATE_BACKUP,
3335-
ipvs->backup_mcast_ifn,
3336-
ipvs->backup_syncid, cb) < 0)
3341+
&ipvs->bcfg, cb) < 0)
33373342
goto nla_put_failure;
33383343

33393344
cb->args[1] = 1;
@@ -3348,25 +3353,33 @@ static int ip_vs_genl_dump_daemons(struct sk_buff *skb,
33483353
static int ip_vs_genl_new_daemon(struct net *net, struct nlattr **attrs)
33493354
{
33503355
struct netns_ipvs *ipvs = net_ipvs(net);
3356+
struct ipvs_sync_daemon_cfg c;
3357+
struct nlattr *a;
33513358
int ret;
33523359

3360+
memset(&c, 0, sizeof(c));
33533361
if (!(attrs[IPVS_DAEMON_ATTR_STATE] &&
33543362
attrs[IPVS_DAEMON_ATTR_MCAST_IFN] &&
33553363
attrs[IPVS_DAEMON_ATTR_SYNC_ID]))
33563364
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);
33573372

33583373
/* The synchronization protocol is incompatible with mixed family
33593374
* services
33603375
*/
3361-
if (net_ipvs(net)->mixed_address_family_dests > 0)
3376+
if (ipvs->mixed_address_family_dests > 0)
33623377
return -EINVAL;
33633378

33643379
rtnl_lock();
33653380
mutex_lock(&ipvs->sync_mutex);
3366-
ret = start_sync_thread(net,
3367-
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]));
3381+
ret = start_sync_thread(net, &c,
3382+
nla_get_u32(attrs[IPVS_DAEMON_ATTR_STATE]));
33703383
mutex_unlock(&ipvs->sync_mutex);
33713384
rtnl_unlock();
33723385
return ret;

0 commit comments

Comments
 (0)