LVS
lvs-devel
Google
 
Web LinuxVirtualServer.org

[PATCH ipvsadm] ipvsadm: new attributes for sync daemon

To: Jesper Dangaard Brouer <brouer@xxxxxxxxxx>
Subject: [PATCH ipvsadm] ipvsadm: new attributes for sync daemon
Cc: Simon Horman <horms@xxxxxxxxxxxx>, lvs-devel@xxxxxxxxxxxxxxx, lvs-users@xxxxxxxxxxxxxxxxxxxxxx
From: Julian Anastasov <ja@xxxxxx>
Date: Sun, 26 Jul 2015 15:12:14 +0300
Add support for --sync-maxlen, --mcast-group, --mcast-port and
--mcast-ttl options for the --start-daemon command.

Signed-off-by: Julian Anastasov <ja@xxxxxx>
---
 ipvsadm.8                 |  55 ++++++++++++++-----
 ipvsadm.c                 | 137 +++++++++++++++++++++++++++++++++++++---------
 libipvs/ip_vs.h           |  31 +++++++++++
 libipvs/ip_vs_nl_policy.c |   6 ++
 libipvs/libipvs.c         |  71 ++++++++++++++++++++++--
 5 files changed, 256 insertions(+), 44 deletions(-)

 It is related to the kernel patches for new parameters for
the sync daemon. If needed I'll post it again later for
inclusion after the kernel patches are included.

diff --git a/ipvsadm.8 b/ipvsadm.8
index 3df3b83..dad1712 100644
--- a/ipvsadm.8
+++ b/ipvsadm.8
@@ -59,7 +59,7 @@ ipvsadm \- Linux Virtual Server administration
 .br
 .B ipvsadm --set \fItcp\fP \fItcpfin\fP \fIudp\fP
 .br
-.B ipvsadm --start-daemon \fIstate\fP [--mcast-interface \fIinterface\fP]
+.B ipvsadm --start-daemon \fIstate\fP [daemon-options]
 .ti 15
 .B [--syncid \fIsyncid\fP]
 .br
@@ -167,7 +167,7 @@ balancer fails, a backup load balancer will takeover, and 
it has state
 of almost all connections, so that almost all established connections
 can continue to access the service.
 .PP
-The sync daemon currently only supports IPv4 connections.
+The sync daemon supports IPv4 and IPv6 connections.
 .TP
 .B --stop-daemon
 Stop the connection synchronization daemon.
@@ -359,18 +359,6 @@ connections drops below its lower connection threshold. If
 will receive new connections when the number of its connections drops
 below three forth of its upper connection threshold.
 .TP
-.B --mcast-interface \fIinterface\fP
-Specify the multicast interface that the sync master daemon sends
-outgoing multicasts through, or the sync backup daemon listens to for
-multicasts.
-.TP
-.B --syncid \fIsyncid\fP
-Specify the \fIsyncid\fP that the sync master daemon fills in the
-SyncID header while sending multicast messages, or the sync backup
-daemon uses to filter out multicast messages not matched with the
-SyncID value. The valid values of \fIsyncid\fP are 0 through to
-255. The default is 0, which means no filtering at all.
-.TP
 .B -c, --connection
 Connection output. The \fIlist\fP command with this option will list
 current IPVS connections.
@@ -438,6 +426,45 @@ One-packet scheduling.
 Used in conjunction with a UDP virtual service or
 a fwmark virtual service that handles only UDP packets.
 All connections are created such that they only schedule one packet.
+.SS PARAMETERS FOR SYNCHRONIZATION DAEMON
+The --start-daemon requires zero or more of the following
+parameters.
+.TP
+.B --syncid \fIsyncid\fP
+Specify the \fIsyncid\fP that the sync master daemon fills in the
+SyncID header while sending multicast messages, or the sync backup
+daemon uses to filter out multicast messages not matched with the
+SyncID value. The valid values of \fIsyncid\fP are 0 through to
+255. The default is 0, which means no filtering at all.
+.TP
+.B --sync-maxlen \fIlength\fP
+Specify the desired length of sync messages (UDP payload size).
+It is expected that backup server will use value not less than
+the used value in master server.
+The valid values of \fIlength\fP are in the 1 .. (65535 - 20 - 8)
+range but the kernel ensures a space for at least one sync message.
+If value is lower than MTU the sync messages will be fragmented by
+IP layer.
+The default value is derived from the MTU value when daemon is started
+but master daemon will not default to value above 1500 for compatibility
+reasons.
+.TP
+.B --mcast-interface \fIinterface\fP
+Specify the multicast interface that the sync master daemon sends
+outgoing multicasts through, or the sync backup daemon listens to for
+multicasts.
+.TP
+.B --mcast-group \fIaddress\fP
+Specify IPv4 or IPv6 multicast address for the sync messages.
+The default value is 224.0.0.81.
+.TP
+.B --mcast-port \fIport\fP
+Specify the UDP port for sync messages.
+The default value is 8848.
+.TP
+.B --mcast-ttl \fIttl\fP
+Specify the TTL value for sync messages (1 .. 255).
+The default value is 1.
 .SH EXAMPLE 1 - Simple Virtual Service
 The following commands configure a Linux Director to distribute
 incoming requests addressed to port 80 on 207.175.44.110 equally to
diff --git a/ipvsadm.c b/ipvsadm.c
index ff1601e..4d1e86e 100644
--- a/ipvsadm.c
+++ b/ipvsadm.c
@@ -183,7 +183,11 @@ static const char* cmdnames[] = {
 #define OPT_ONEPACKET          0x200000
 #define OPT_PERSISTENCE_ENGINE  0x400000
 #define OPT_SCHED_FLAGS                0x800000
-#define NUMBER_OF_OPT          24
+#define OPT_MCAST_GROUP                0x01000000
+#define OPT_MCAST_PORT         0x02000000
+#define OPT_MCAST_TTL          0x04000000
+#define OPT_SYNC_MAXLEN        0x08000000
+#define NUMBER_OF_OPT          28
 
 static const char* optnames[] = {
        "numeric",
@@ -210,6 +214,10 @@ static const char* optnames[] = {
        "ops",
        "pe",
        "sched-flags",
+       "mcast-group",
+       "mcast-port",
+       "mcast-ttl",
+       "sync-maxlen",
 };
 
 /*
@@ -222,21 +230,21 @@ static const char* optnames[] = {
  */
 static const char commands_v_options[NUMBER_OF_CMD][NUMBER_OF_OPT] =
 {
-       /*   -n   -c   svc  -s   -p   -M   -r   fwd  -w   -x   -y   -mc  tot  
dmn  -st  -rt  thr  -pc  srt  sid  -ex  ops  -pe  -b */
-/*ADD*/     {'x', 'x', '+', ' ', ' ', ' ', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', ' ', ' ', ' '},
-/*EDIT*/    {'x', 'x', '+', ' ', ' ', ' ', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', ' ', ' ', ' '},
-/*DEL*/     {'x', 'x', '+', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'},
-/*FLUSH*/   {'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'},
-/*LIST*/    {' ', '1', '1', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', '1', 
'1', ' ', ' ', ' ', ' ', ' ', ' ', ' ', 'x', 'x', 'x'},
-/*ADDSRV*/  {'x', 'x', '+', 'x', 'x', 'x', '+', ' ', ' ', ' ', ' ', 'x', 'x', 
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'},
-/*DELSRV*/  {'x', 'x', '+', 'x', 'x', 'x', '+', 'x', 'x', 'x', 'x', 'x', 'x', 
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'},
-/*EDITSRV*/ {'x', 'x', '+', 'x', 'x', 'x', '+', ' ', ' ', ' ', ' ', 'x', 'x', 
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'},
-/*TIMEOUT*/ {'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'},
-/*STARTD*/  {'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', ' ', 'x', 
'x', 'x', 'x', 'x', 'x', 'x', ' ', 'x', 'x', 'x', 'x'},
-/*STOPD*/   {'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 
'x', 'x', 'x', 'x', 'x', 'x', ' ', 'x', 'x', 'x', 'x'},
-/*RESTORE*/ {'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'},
-/*SAVE*/    {' ', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'},
-/*ZERO*/    {'x', 'x', ' ', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'},
+       /*   -n   -c   svc  -s   -p   -M   -r   fwd  -w   -x   -y   -mc  tot  
dmn  -st  -rt  thr  -pc  srt  sid  -ex  ops  -pe  -b   grp  port ttl  size */
+/*ADD*/     {'x', 'x', '+', ' ', ' ', ' ', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', ' ', ' ', ' ', 'x', 'x', 'x', 'x'},
+/*EDIT*/    {'x', 'x', '+', ' ', ' ', ' ', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', ' ', ' ', ' ', 'x', 'x', 'x', 'x'},
+/*DEL*/     {'x', 'x', '+', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'},
+/*FLUSH*/   {'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'},
+/*LIST*/    {' ', '1', '1', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', '1', 
'1', ' ', ' ', ' ', ' ', ' ', ' ', ' ', 'x', 'x', 'x', 'x', 'x', 'x', 'x'},
+/*ADDSRV*/  {'x', 'x', '+', 'x', 'x', 'x', '+', ' ', ' ', ' ', ' ', 'x', 'x', 
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'},
+/*DELSRV*/  {'x', 'x', '+', 'x', 'x', 'x', '+', 'x', 'x', 'x', 'x', 'x', 'x', 
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'},
+/*EDITSRV*/ {'x', 'x', '+', 'x', 'x', 'x', '+', ' ', ' ', ' ', ' ', 'x', 'x', 
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'},
+/*TIMEOUT*/ {'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'},
+/*STARTD*/  {'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', ' ', 'x', 
'x', 'x', 'x', 'x', 'x', 'x', ' ', 'x', 'x', 'x', 'x', ' ', ' ', ' ', ' '},
+/*STOPD*/   {'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 
'x', 'x', 'x', 'x', 'x', 'x', ' ', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'},
+/*RESTORE*/ {'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'},
+/*SAVE*/    {' ', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'},
+/*ZERO*/    {'x', 'x', ' ', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'},
 };
 
 /* printing format flags */
@@ -288,6 +296,10 @@ enum {
        TAG_NO_SORT,
        TAG_PERSISTENCE_ENGINE,
        TAG_SCTP_SERVICE,
+       TAG_MCAST_GROUP,
+       TAG_MCAST_PORT,
+       TAG_MCAST_TTL,
+       TAG_SYNC_MAXLEN,
 };
 
 /* various parsing helpers & parsing functions */
@@ -475,6 +487,14 @@ parse_options(int argc, char **argv, struct 
ipvs_command_entry *ce,
                  NULL, NULL },
                { "sched-flags", 'b', POPT_ARG_STRING, &optarg, 'b',
                  NULL, NULL },
+               { "mcast-group", '\0', POPT_ARG_STRING, &optarg,
+                 TAG_MCAST_GROUP, NULL, NULL },
+               { "mcast-port", '\0', POPT_ARG_STRING, &optarg,
+                 TAG_MCAST_PORT, NULL, NULL },
+               { "mcast-ttl", '\0', POPT_ARG_STRING, &optarg,
+                 TAG_MCAST_TTL, NULL, NULL },
+               { "sync-maxlen", '\0', POPT_ARG_STRING, &optarg,
+                 TAG_SYNC_MAXLEN, NULL, NULL },
                { NULL, 0, 0, NULL, 0, NULL, NULL }
        };
 
@@ -712,6 +732,47 @@ parse_options(int argc, char **argv, struct 
ipvs_command_entry *ce,
                        snprintf(sched_flags_arg, sizeof(sched_flags_arg),
                                "%s", optarg);
                        break;
+               case TAG_MCAST_GROUP:
+                       set_option(options, OPT_MCAST_GROUP);
+                       if (strchr(optarg, ':')) {
+                               if (inet_pton(AF_INET6, optarg,
+                                             &ce->daemon.mcast_group) <= 0 ||
+                                   !IN6_IS_ADDR_MULTICAST(
+                                    &ce->daemon.mcast_group.in6))
+                                       fail(2, "invalid IPv6 mcast-group `%s'",
+                                            optarg);
+                               ce->daemon.mcast_af = AF_INET6;
+                       } else {
+                               if (inet_pton(AF_INET, optarg,
+                                             &ce->daemon.mcast_group) <= 0 ||
+                                   !IN_MULTICAST(ntohl(
+                                                 ce->daemon.mcast_group.ip)))
+                                       fail(2, "invalid IPv4 mcast-group `%s'",
+                                            optarg);
+                               ce->daemon.mcast_af = AF_INET;
+                       }
+                       break;
+               case TAG_MCAST_PORT:
+                       set_option(options, OPT_MCAST_PORT);
+                       parse = string_to_number(optarg, 1, 65535);
+                       if (parse == -1)
+                               fail(2, "illegal mcast-port specified");
+                       ce->daemon.mcast_port = parse;
+                       break;
+               case TAG_MCAST_TTL:
+                       set_option(options, OPT_MCAST_TTL);
+                       parse = string_to_number(optarg, 1, 255);
+                       if (parse == -1)
+                               fail(2, "illegal mcast-ttl specified");
+                       ce->daemon.mcast_ttl = parse;
+                       break;
+               case TAG_SYNC_MAXLEN:
+                       set_option(options, OPT_SYNC_MAXLEN);
+                       parse = string_to_number(optarg, 1, 65535 - 20 - 8);
+                       if (parse == -1)
+                               fail(2, "illegal sync-maxlen specified");
+                       ce->daemon.sync_maxlen = parse;
+                       break;
                default:
                        fail(2, "invalid option `%s'",
                             poptBadOption(context, POPT_BADOPTION_NOALIAS));
@@ -1182,8 +1243,8 @@ static void usage_exit(const char *program, const int 
exit_status)
                "  %s -L|l [virtual-service] [options]\n"
                "  %s -Z [virtual-service]\n"
                "  %s --set tcp tcpfin udp\n"
-               "  %s --start-daemon state [--mcast-interface interface] 
[--syncid sid]\n"
-               "  %s --stop-daemon state\n"
+               "  %s --start-daemon {master|backup} [daemon-options]\n"
+               "  %s --stop-daemon {master|backup}\n"
                "  %s -h\n\n",
                program, program, program,
                program, program, program, program, program,
@@ -1233,8 +1294,6 @@ static void usage_exit(const char *program, const int 
exit_status)
                "  --weight       -w weight            capacity of real 
server\n"
                "  --u-threshold  -x uthreshold        upper threshold of 
connections\n"
                "  --l-threshold  -y lthreshold        lower threshold of 
connections\n"
-               "  --mcast-interface interface         multicast interface for 
connection sync\n"
-               "  --syncid sid                        syncid for connection 
sync (default=255)\n"
                "  --connection   -c                   output of current IPVS 
connections\n"
                "  --timeout                           output of timeout (tcp 
tcpfin udp)\n"
                "  --daemon                            output of daemon 
information\n"
@@ -1250,6 +1309,16 @@ static void usage_exit(const char *program, const int 
exit_status)
                "  --sched-flags  -b flags             scheduler flags 
(comma-separated)\n",
                DEF_SCHED);
 
+       fprintf(stream,
+               "Daemon Options:\n"
+               "  --syncid sid                        syncid for connection 
sync (default=255)\n"
+               "  --sync-maxlen length                Max sync message length 
(default=1472)\n"
+               "  --mcast-interface interface         multicast interface for 
connection sync\n"
+               "  --mcast-group address               IPv4/IPv6 group 
(default=224.0.0.81)\n"
+               "  --mcast-port port                   UDP port 
(default=8848)\n"
+               "  --mcast-ttl ttl                     Multicast TTL 
(default=1)\n"
+               );
+
        exit(exit_status);
 }
 
@@ -1793,12 +1862,30 @@ static void list_daemon(void)
                exit(1);
 
        for (i = 0; i < 2; i++) {
+               char *type;
+
                if (u[i].state & IP_VS_STATE_MASTER)
-                       printf("master sync daemon (mcast=%s, syncid=%d)\n",
-                              u[i].mcast_ifn, u[i].syncid);
-               if (u[i].state & IP_VS_STATE_BACKUP)
-                       printf("backup sync daemon (mcast=%s, syncid=%d)\n",
-                              u[i].mcast_ifn, u[i].syncid);
+                       type = "master";
+               else if (u[i].state & IP_VS_STATE_BACKUP)
+                       type = "backup";
+               else
+                       continue;
+               printf("%s sync daemon (mcast=%s, syncid=%d",
+                      type, u[i].mcast_ifn, u[i].syncid);
+               if (u[i].sync_maxlen)
+                       printf(", maxlen=%u", u[i].sync_maxlen);
+               if (u[i].mcast_af != AF_UNSPEC) {
+                       char addr[INET6_ADDRSTRLEN];
+
+                       if (inet_ntop(u[i].mcast_af, &u[i].mcast_group,
+                                     addr, sizeof(addr)))
+                               printf(", group=%s", addr);
+               }
+               if (u[i].mcast_port)
+                       printf(", port=%u", u[i].mcast_port);
+               if (u[i].mcast_ttl)
+                       printf(", ttl=%u", u[i].mcast_ttl);
+               printf(")\n");
        }
        free(u);
 }
diff --git a/libipvs/ip_vs.h b/libipvs/ip_vs.h
index 5a42a0c..f855cc6 100644
--- a/libipvs/ip_vs.h
+++ b/libipvs/ip_vs.h
@@ -348,6 +348,17 @@ struct ip_vs_timeout_user {
 
 
 /* The argument to IP_VS_SO_GET_DAEMON */
+struct ip_vs_daemon_kern {
+       /* sync daemon state (master/backup) */
+       int                     state;
+
+       /* multicast interface name */
+       char                    mcast_ifn[IP_VS_IFNAME_MAXLEN];
+
+       /* SyncID we belong to */
+       int                     syncid;
+};
+
 struct ip_vs_daemon_user {
        /* sync daemon state (master/backup) */
        int                     state;
@@ -357,6 +368,21 @@ struct ip_vs_daemon_user {
 
        /* SyncID we belong to */
        int                     syncid;
+
+       /* UDP Payload Size */
+       int                     sync_maxlen;
+
+       /* Multicast Port (base) */
+       u_int16_t               mcast_port;
+
+       /* Multicast TTL */
+       u_int16_t               mcast_ttl;
+
+       /* Multicast Address Family */
+       u_int16_t               mcast_af;
+
+       /* Multicast Address */
+       union nf_inet_addr      mcast_group;
 };
 
 
@@ -488,6 +514,11 @@ enum {
        IPVS_DAEMON_ATTR_STATE,         /* sync daemon state (master/backup) */
        IPVS_DAEMON_ATTR_MCAST_IFN,     /* multicast interface name */
        IPVS_DAEMON_ATTR_SYNC_ID,       /* SyncID we belong to */
+       IPVS_DAEMON_ATTR_SYNC_MAXLEN,   /* UDP Payload Size */
+       IPVS_DAEMON_ATTR_MCAST_GROUP,   /* IPv4 Multicast Address */
+       IPVS_DAEMON_ATTR_MCAST_GROUP6,  /* IPv6 Multicast Address */
+       IPVS_DAEMON_ATTR_MCAST_PORT,    /* Multicast Port (base) */
+       IPVS_DAEMON_ATTR_MCAST_TTL,     /* Multicast TTL */
        __IPVS_DAEMON_ATTR_MAX,
 };
 
diff --git a/libipvs/ip_vs_nl_policy.c b/libipvs/ip_vs_nl_policy.c
index c80083e..2d65224 100644
--- a/libipvs/ip_vs_nl_policy.c
+++ b/libipvs/ip_vs_nl_policy.c
@@ -65,6 +65,12 @@ struct nla_policy ipvs_daemon_policy[IPVS_DAEMON_ATTR_MAX + 
1] = {
        [IPVS_DAEMON_ATTR_MCAST_IFN]    = { .type = NLA_STRING,
                                            .maxlen = IP_VS_IFNAME_MAXLEN },
        [IPVS_DAEMON_ATTR_SYNC_ID]      = { .type = NLA_U32 },
+       [IPVS_DAEMON_ATTR_SYNC_MAXLEN]  = { .type = NLA_U16 },
+       [IPVS_DAEMON_ATTR_MCAST_GROUP]  = { .type = NLA_U32 },
+       [IPVS_DAEMON_ATTR_MCAST_GROUP6] = { .type = NLA_UNSPEC,
+                                           .maxlen = sizeof(struct in6_addr) },
+       [IPVS_DAEMON_ATTR_MCAST_PORT]   = { .type = NLA_U16 },
+       [IPVS_DAEMON_ATTR_MCAST_TTL]    = { .type = NLA_U8 },
 };
 
 #endif /* LIBIPVS_USE_NL */
diff --git a/libipvs/libipvs.c b/libipvs/libipvs.c
index 0bfb428..614001d 100644
--- a/libipvs/libipvs.c
+++ b/libipvs/libipvs.c
@@ -485,6 +485,8 @@ nla_put_failure:
 
 int ipvs_start_daemon(ipvs_daemon_t *dm)
 {
+       struct ip_vs_daemon_kern dmk;
+
        ipvs_func = ipvs_start_daemon;
 #ifdef LIBIPVS_USE_NL
        if (try_nl) {
@@ -499,6 +501,22 @@ int ipvs_start_daemon(ipvs_daemon_t *dm)
                NLA_PUT_U32(msg, IPVS_DAEMON_ATTR_STATE, dm->state);
                NLA_PUT_STRING(msg, IPVS_DAEMON_ATTR_MCAST_IFN, dm->mcast_ifn);
                NLA_PUT_U32(msg, IPVS_DAEMON_ATTR_SYNC_ID, dm->syncid);
+               if (dm->sync_maxlen)
+                       NLA_PUT_U16(msg, IPVS_DAEMON_ATTR_SYNC_MAXLEN,
+                                   dm->sync_maxlen);
+               if (dm->mcast_port)
+                       NLA_PUT_U16(msg, IPVS_DAEMON_ATTR_MCAST_PORT,
+                                   dm->mcast_port);
+               if (dm->mcast_ttl)
+                       NLA_PUT_U8(msg, IPVS_DAEMON_ATTR_MCAST_TTL,
+                                  dm->mcast_ttl);
+               if (AF_INET6 == dm->mcast_af)
+                       NLA_PUT(msg, IPVS_DAEMON_ATTR_MCAST_GROUP6,
+                               sizeof(dm->mcast_group.in6),
+                               &dm->mcast_group.in6);
+               else if (AF_INET == dm->mcast_af)
+                       NLA_PUT_U32(msg, IPVS_DAEMON_ATTR_MCAST_GROUP,
+                                   dm->mcast_group.ip);
 
                nla_nest_end(msg, nl_daemon);
 
@@ -509,13 +527,19 @@ nla_put_failure:
                return -1;
        }
 #endif
+       memset(&dmk, 0, sizeof(dmk));
+       dmk.state = dm->state;
+       strcpy(dmk.mcast_ifn, dm->mcast_ifn);
+       dmk.syncid = dm->syncid;
        return setsockopt(sockfd, IPPROTO_IP, IP_VS_SO_SET_STARTDAEMON,
-                         (char *)dm, sizeof(*dm));
+                         (char *)&dmk, sizeof(dmk));
 }
 
 
 int ipvs_stop_daemon(ipvs_daemon_t *dm)
 {
+       struct ip_vs_daemon_kern dmk;
+
        ipvs_func = ipvs_stop_daemon;
 #ifdef LIBIPVS_USE_NL
        if (try_nl) {
@@ -540,8 +564,10 @@ nla_put_failure:
                return -1;
        }
 #endif
+       memset(&dmk, 0, sizeof(dmk));
+       dmk.state = dm->state;
        return setsockopt(sockfd, IPPROTO_IP, IP_VS_SO_SET_STOPDAEMON,
-                         (char *)dm, sizeof(*dm));
+                         (char *)&dmk, sizeof(dmk));
 }
 
 #ifdef LIBIPVS_USE_NL
@@ -1065,6 +1091,7 @@ static int ipvs_daemon_parse_cb(struct nl_msg *msg, void 
*arg)
        struct nlattr *attrs[IPVS_CMD_ATTR_MAX + 1];
        struct nlattr *daemon_attrs[IPVS_DAEMON_ATTR_MAX + 1];
        ipvs_daemon_t *u = (ipvs_daemon_t *)arg;
+       struct nlattr *a;
        int i = 0;
 
        /* We may get two daemons.  If we've already got one, this is the 
second */
@@ -1089,26 +1116,54 @@ static int ipvs_daemon_parse_cb(struct nl_msg *msg, 
void *arg)
                IP_VS_IFNAME_MAXLEN);
        u[i].syncid = nla_get_u32(daemon_attrs[IPVS_DAEMON_ATTR_SYNC_ID]);
 
+       a = daemon_attrs[IPVS_DAEMON_ATTR_SYNC_MAXLEN];
+       if (a)
+               u[i].sync_maxlen = nla_get_u16(a);
+
+       a = daemon_attrs[IPVS_DAEMON_ATTR_MCAST_PORT];
+       if (a)
+               u[i].mcast_port = nla_get_u16(a);
+
+       a = daemon_attrs[IPVS_DAEMON_ATTR_MCAST_TTL];
+       if (a)
+               u[i].mcast_ttl = nla_get_u8(a);
+
+       a = daemon_attrs[IPVS_DAEMON_ATTR_MCAST_GROUP];
+       if (a) {
+               u[i].mcast_af = AF_INET;
+               u[i].mcast_group.ip = nla_get_u32(a);
+       } else {
+               a = daemon_attrs[IPVS_DAEMON_ATTR_MCAST_GROUP6];
+               if (a) {
+                       u[i].mcast_af = AF_INET6;
+                       memcpy(&u[i].mcast_group.in6, nla_data(a),
+                              sizeof(u[i].mcast_group.in6));
+               }
+       }
+
        return NL_OK;
 }
 #endif
 
 ipvs_daemon_t *ipvs_get_daemon(void)
 {
+       struct ip_vs_daemon_kern dmk[2];
        ipvs_daemon_t *u;
        socklen_t len;
+       int i;
 
        /* note that we need to get the info about two possible
           daemons, master and backup. */
        len = sizeof(*u) * 2;
-       if (!(u = malloc(len)))
+       u = calloc(len, 1);
+       if (!u)
                return NULL;
 
        ipvs_func = ipvs_get_daemon;
 #ifdef LIBIPVS_USE_NL
        if (try_nl) {
                struct nl_msg *msg;
-               memset(u, 0, len);
+
                msg = ipvs_nl_message(IPVS_CMD_GET_DAEMON, NLM_F_DUMP);
                if (msg && (ipvs_nl_send_message(msg, ipvs_daemon_parse_cb, u) 
== 0))
                        return u;
@@ -1117,10 +1172,16 @@ ipvs_daemon_t *ipvs_get_daemon(void)
                return NULL;
        }
 #endif
-       if (getsockopt(sockfd, IPPROTO_IP, IP_VS_SO_GET_DAEMON, (char *)u, 
&len)) {
+       if (getsockopt(sockfd, IPPROTO_IP, IP_VS_SO_GET_DAEMON, (char *)dmk,
+                      &len)) {
                free(u);
                return NULL;
        }
+       for (i = 0; i < 2; i++) {
+               u[i].state = dmk[i].state;
+               strncpy(u[i].mcast_ifn, dmk[i].mcast_ifn, IP_VS_IFNAME_MAXLEN);
+               u[i].syncid = dmk[i].syncid;
+       }
        return u;
 }
 
-- 
1.9.3

--
To unsubscribe from this list: send the line "unsubscribe lvs-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

<Prev in Thread] Current Thread [Next in Thread>
  • [PATCH ipvsadm] ipvsadm: new attributes for sync daemon, Julian Anastasov <=