Make fec parameters configurable.
authorAndre Noll <maan@systemlinux.org>
Sun, 1 Mar 2009 18:26:04 +0000 (19:26 +0100)
committerAndre Noll <maan@systemlinux.org>
Sun, 1 Mar 2009 18:26:04 +0000 (19:26 +0100)
This patch allows to specify the fec parameters in the add subcommand
like this:

para_client sender udp add 224.0.1.38:8000/1400:63:64

command.c
send.h
send_common.c
server.h
udp_send.c

index deb21a6..b59fae7 100644 (file)
--- a/command.c
+++ b/command.c
@@ -204,10 +204,9 @@ static int check_sender_args(int argc, char * const * argv, struct sender_comman
                break;
        case SENDER_ADD:
        case SENDER_DELETE:
-               if (argc != 4 || parse_url(argv[3], scd->host,
-                               sizeof(scd->host), &scd->port) == NULL)
+               if (argc != 4)
                        return -E_COMMAND_SYNTAX;
-               break;
+               return parse_fec_url(argv[3], scd);
        default:
                return -E_COMMAND_SYNTAX;
        }
diff --git a/send.h b/send.h
index c1ed00c..7087c26 100644 (file)
--- a/send.h
+++ b/send.h
@@ -143,3 +143,4 @@ char *generic_sender_help(void);
 struct sender_client *accept_sender_client(struct sender_status *ss);
 int send_queued_chunks(int fd, struct chunk_queue *cq,
                size_t max_bytes_per_write);
+int parse_fec_url(const char *arg, struct sender_command_data *scd);
index f570273..448ddfe 100644 (file)
@@ -393,3 +393,76 @@ char *generic_sender_help(void)
                "example: allow 127.0.0.1 32\n"
        );
 }
+
+static int parse_fec_parms(const char *arg, struct sender_command_data *scd)
+{
+       int32_t val;
+       char *a = para_strdup(arg), *b = a, *e = strchr(b, ':');
+       int ret = -E_COMMAND_SYNTAX;
+
+       /* parse max slice bytes */
+       if (!e)
+               goto out;
+       *e = '\0';
+       ret = para_atoi32(b, &val);
+       if (ret < 0)
+               goto out;
+       ret = -ERRNO_TO_PARA_ERROR(EINVAL);
+       if (val < 0 || val > 65535)
+               goto out;
+       scd->max_slice_bytes = val;
+       /* parse data_slices_per_group */
+       b = e + 1;
+       e = strchr(b, ':');
+       ret = -E_COMMAND_SYNTAX;
+       if (!e)
+               goto out;
+       *e = '\0';
+       ret = para_atoi32(b, &val);
+       if (ret < 0)
+               goto out;
+       ret = -ERRNO_TO_PARA_ERROR(EINVAL);
+       if (val < 0 || val > 255)
+               goto out;
+       scd->data_slices_per_group = val;
+       /* parse slices_per_group */
+       b = e + 1;
+       ret = para_atoi32(b, &val);
+       if (ret < 0)
+               goto out;
+       ret = -ERRNO_TO_PARA_ERROR(EINVAL);
+       if (val < 0 || val < scd->data_slices_per_group)
+               goto out;
+       scd->slices_per_group = val;
+       ret = 0;
+out:
+       free(a);
+       return ret;
+}
+
+int parse_fec_url(const char *arg, struct sender_command_data *scd)
+{
+       int ret;
+       ssize_t len = sizeof(scd->host);
+       char *a = para_strdup(arg), *p = strchr(a, '/');
+
+       if (p) {
+               *p = '\0';
+               len = strlen(a);
+       }
+       ret = -ERRNO_TO_PARA_ERROR(EINVAL);
+       if (!parse_url(a, scd->host, len, &scd->port))
+               goto out;
+       if (p) {
+               ret = parse_fec_parms(p + 1, scd);
+               goto out;
+       }
+       /* use default fec parameters. */
+       scd->max_slice_bytes = 1490;
+       scd->slices_per_group = 16;
+       scd->data_slices_per_group = 14;
+       ret = 0;
+out:
+       free(a);
+       return ret;
+}
index a0dfd2d..cf17c0e 100644 (file)
--- a/server.h
+++ b/server.h
@@ -42,6 +42,12 @@ struct sender_command_data{
        int netmask;
        /** The port number for add/remove. */
        int port;
+       /** Maximal slice size. */
+       uint16_t max_slice_bytes;
+       /** Number of data slices plus redundant slices. */
+       uint8_t slices_per_group;
+       /** Number of slices minus number of redundant slices. */
+       uint8_t data_slices_per_group;
 };
 
 /**
index 7585eaa..a21f478 100644 (file)
@@ -178,7 +178,9 @@ static int udp_init_session(struct udp_target *ut)
        }
        add_close_on_fork_list(ut->fd);
        ut->cq = cq_new(UDP_CQ_BYTES);
-       PARA_NOTICE_LOG("sending to udp %s#%d\n", ut->host, ut->port);
+       PARA_NOTICE_LOG("sending to udp %s#%d using fec parms %d:%d:%d\n",
+               ut->host, ut->port , ut->fcp.max_slice_bytes,
+               ut->fcp.data_slices_per_group, ut->fcp.slices_per_group);
        return 1;
 }
 
@@ -257,19 +259,18 @@ fail:
        return ret;
 }
 
-static void udp_add_target(const char *host, int port)
+static void udp_add_target(struct sender_command_data *scd)
 {
        struct udp_target *ut = para_calloc(sizeof(struct udp_target));
 
-       strncpy(ut->host, host, sizeof(ut->host));
-       ut->port = port > 0 ? port : conf.udp_default_port_arg;
+       strncpy(ut->host, scd->host, sizeof(ut->host));
+       ut->port = scd->port > 0 ? scd->port : conf.udp_default_port_arg;
        ut->fd = -1; /* not yet connected */
-       PARA_INFO_LOG("adding to target list (%s#%d)\n",
-                     ut->host, ut->port);
+       PARA_INFO_LOG("adding to target list (%s#%d)\n", ut->host, ut->port);
        para_list_add(&ut->node, &targets);
-       ut->fcp.slices_per_group = 16;
-       ut->fcp.data_slices_per_group = 14;
-       ut->fcp.max_slice_bytes = 1400;
+       ut->fcp.slices_per_group = scd->slices_per_group;
+       ut->fcp.data_slices_per_group = scd->data_slices_per_group;
+       ut->fcp.max_slice_bytes = scd->max_slice_bytes;
        ut->fcp.send = udp_send_fec;
        ut->fcp.private_data = ut;
        vss_add_fec_client(&ut->fcp, &ut->fc);
@@ -277,7 +278,7 @@ static void udp_add_target(const char *host, int port)
 
 static int udp_com_add(struct sender_command_data *scd)
 {
-       udp_add_target(scd->host, scd->port);
+       udp_add_target(scd);
        return 1;
 }
 
@@ -309,25 +310,29 @@ static char *udp_info(void)
 
 static void udp_init_target_list(void)
 {
-       char    host[MAX_HOSTLEN];
-       int     port, i;
+       struct sender_command_data scd;
+       int i;
 
        INIT_LIST_HEAD(&targets);
-       for (i = 0; i < conf.udp_target_given; i++)
-               if (parse_url(conf.udp_target_arg[i], host,
-                                       sizeof(host), &port) == NULL)
+       for (i = 0; i < conf.udp_target_given; i++) {
+               if (parse_fec_url(conf.udp_target_arg[i], &scd) < 0) {
                        PARA_CRIT_LOG("syntax error for udp target option "
-                                     "#%d, ignoring\n", i);
-               else
-                       udp_add_target(host, port);
+                               "#%d, ignoring\n", i);
+                       continue;
+               }
+               udp_add_target(&scd);
+       }
 }
 
 static char *udp_help(void)
 {
        return make_message(
                "usage: {on|off}\n"
-               "usage: {add|delete} host[:port]\n"
+               "usage: {add|delete} host[:port][/packet_size:k:n]\n"
                "examples: add 224.0.1.38:1500  (IPv4 multicast)\n"
+               "          add 224.0.1.38:1500/1400:14:16\n"
+               "              (likewise, using 1400 byte packets, with 14\n"
+               "               data slices per 16 slice FEC group)\n"
                "          add 10.10.1.42       (using default port)\n"
                "          add [FF05::42]:1500  (IPv6 multicast)\n"
                "          add [::1]            (IPv6 localhost/default port)\n"