Dear Aaron, The general idea looks good to me.
Just some comments inline On 3 December 2015 at 05:23, Aaron Conole <acon...@redhat.com> wrote: > Existing DPDK integration is provided by use of command line options which > must be split out and passed to librte in a special manner. However, this > forces any configuration to be passed by way of a special DPDK flag, and > interferes with ovs+dpdk packaging solutions. > > This commit delays dpdk initialization until after the OVS database > connection > is established, and then initializes librte. It pulls all of the config > data > from the OVS database, and assembles a new argv/argc pair to be passed > along. > > Signed-off-by: Aaron Conole <acon...@redhat.com> > --- > lib/netdev-dpdk.c | 126 > ++++++++++++++++++++++++++++++++---------------- > lib/netdev-dpdk.h | 12 ++--- > utilities/ovs-ctl.in | 12 ++--- > vswitchd/bridge.c | 3 ++ > vswitchd/ovs-vswitchd.c | 27 ----------- > 5 files changed, 99 insertions(+), 81 deletions(-) > > diff --git a/lib/netdev-dpdk.c b/lib/netdev-dpdk.c > index e3a0771..f3e0840 100644 > --- a/lib/netdev-dpdk.c > +++ b/lib/netdev-dpdk.c > @@ -29,6 +29,7 @@ > #include <stdio.h> > #include <sys/types.h> > #include <sys/stat.h> > +#include <getopt.h> > > #include "dirs.h" > #include "dp-packet.h" > @@ -49,6 +50,8 @@ > #include "timeval.h" > #include "unixctl.h" > #include "openvswitch/vlog.h" > +#include "smap.h" > +#include "vswitch-idl.h" > > #include "rte_config.h" > #include "rte_mbuf.h" > @@ -2107,10 +2110,14 @@ unlock_dpdk: > > static int > process_vhost_flags(char *flag, char *default_val, int size, > - char **argv, char **new_val) > + const struct ovsrec_open_vswitch *ovs_cfg, > + char **new_val) > { > + const char *val; > int changed = 0; > > + val = smap_get(&ovs_cfg->other_config, flag); > + > /* Depending on which version of vhost is in use, process the > vhost-specific > * flag if it is provided on the vswitchd command line, otherwise > resort to > * a default value. > @@ -2120,9 +2127,9 @@ process_vhost_flags(char *flag, char *default_val, > int size, > * For vhost-cuse: Process "-cuse_dev_name" to set the custom name of > the > * vhost-cuse character device. > */ > - if (!strcmp(argv[1], flag) && (strlen(argv[2]) <= size)) { > + if (val && (strlen(val) <= size)) { > changed = 1; > - *new_val = strdup(argv[2]); > + *new_val = strdup(val); > VLOG_INFO("User-provided %s in use: %s", flag, *new_val); > } else { > VLOG_INFO("No %s provided - defaulting to %s", flag, default_val); > @@ -2132,34 +2139,77 @@ process_vhost_flags(char *flag, char *default_val, > int size, > return changed; > } > > -int > -dpdk_init(int argc, char **argv) > +static char ** > +grow_argv(char ***argv, size_t cur_siz, size_t grow_by) > { > - int result; > - int base = 0; > - char *pragram_name = argv[0]; > + char **new_argv = realloc(*argv, sizeof(char *) * (cur_siz + > grow_by)); > + return new_argv; > +} > > - if (argc < 2 || strcmp(argv[1], "--dpdk")) > - return 0; > +static int > +get_dpdk_args(const struct ovsrec_open_vswitch *ovs_cfg, char ***argv) > +{ > + struct dpdk_options_map { > + const char *ovs_configuration; > + const char *dpdk_option; > + bool default_enabled; > + const char *default_value; > + } opts[] = { > + {"dpdk_core_mask", "-c", true, "0x1"}, > + {"dpdk_mem_channels", "-n", true, "4"}, > + {"dpdk_alloc_mem", "-m", false, NULL}, > + {"dpdk_socket_mem", "--socket-mem", false, NULL}, > + {"dpdk_hugepage_dir", "--huge-dir", false, NULL}, > + }; > + int i, ret = 1; > + > + for(i = 0; i < (sizeof(opts) / sizeof(opts[0])); ++i){ > + const char *lookup = smap_get(&ovs_cfg->other_config, > + opts[i].ovs_configuration); > + if(!lookup && opts[i].default_enabled) > + lookup = opts[i].default_value; > + > + if(lookup) { > + char **newargv = grow_argv(argv, ret, 2); > + > + if (!newargv) > + return ret; > + > + *argv = newargv; > + (*argv)[ret++] = strdup(opts[i].dpdk_option); > + (*argv)[ret++] = strdup(lookup); > + } > + } > > - /* Remove the --dpdk argument from arg list.*/ > - argc--; > - argv++; > + return ret; > +} > > argv shall be NULL terminated, i.e. argv[argc] shall be NULL. - /* Reject --user option */ > - int i; > - for (i = 0; i < argc; i++) { > - if (!strcmp(argv[i], "--user")) { > - VLOG_ERR("Can not mix --dpdk and --user options, aborting."); > - } > +void > +dpdk_init(const struct ovsrec_open_vswitch *ovs_cfg) > +{ > + static int initialized = 0; > + > + char **argv; > + int result; > + int argc; > + > + if(initialized || !smap_get_bool(&ovs_cfg->other_config, "dpdk", > false)){ > + return; > } > + > + initialized = 1; > > + VLOG_INFO("DPDK Enabled, initializing"); > + > + /* TODO should check for user permissions. DPDK requires root user. */ > + > #ifdef VHOST_CUSE > - if (process_vhost_flags("-cuse_dev_name", strdup("vhost-net"), > - PATH_MAX, argv, &cuse_dev_name)) { > + if (process_vhost_flags("cuse_dev_name", strdup("vhost-net"), > + PATH_MAX, ovs_cfg, &cuse_dev_name)) { > + > #else > - if (process_vhost_flags("-vhost_sock_dir", strdup(ovs_rundir()), > - NAME_MAX, argv, &vhost_sock_dir)) { > + if (process_vhost_flags("vhost_sock_dir", strdup(ovs_rundir()), > + NAME_MAX, ovs_cfg, &vhost_sock_dir)) { > struct stat s; > int err; > > @@ -2167,40 +2217,34 @@ dpdk_init(int argc, char **argv) > if (err) { > VLOG_ERR("vHostUser socket DIR '%s' does not exist.", > vhost_sock_dir); > - return err; > + return; > } > #endif > - /* Remove the vhost flag configuration parameters from the > argument > - * list, so that the correct elements are passed to the DPDK > - * initialization function > - */ > - argc -= 2; > - argv += 2; /* Increment by two to bypass the vhost flag > arguments */ > - base = 2; > } > > - /* Keep the program name argument as this is needed for call to > - * rte_eal_init() > - */ > - argv[0] = pragram_name; > + argv = (char **)malloc(sizeof(char *)); > + *argv = strdup("ovs"); /* TODO use prctl to get process name */ > + > + argc = get_dpdk_args(ovs_cfg, &argv); > + > + optind = 1; > > /* Make sure things are initialized ... */ > result = rte_eal_init(argc, argv); > if (result < 0) { > ovs_abort(result, "Cannot init EAL"); > } > + > + for(result = 0; result < argc-1; ++result) > + free(argv[result]); > + > + free(argv); > > I am not sure if freeing argv is valid in this case, C99 standard states that it shall remain valid until the program terminates. > rte_memzone_dump(stdout); > rte_eal_init_ret = 0; > > - if (argc > result) { > - argv[result] = argv[0]; > - } > - > /* We are called from the main thread here */ > RTE_PER_LCORE(_lcore_id) = NON_PMD_CORE_ID; > - > - return result + 1 + base; > } > > static const struct netdev_class dpdk_class = > diff --git a/lib/netdev-dpdk.h b/lib/netdev-dpdk.h > index 646d3e2..e01adb3 100644 > --- a/lib/netdev-dpdk.h > +++ b/lib/netdev-dpdk.h > @@ -4,6 +4,7 @@ > #include <config.h> > > struct dp_packet; > +struct ovsrec_open_vswitch; > > #ifdef DPDK_NETDEV > > @@ -22,7 +23,7 @@ struct dp_packet; > > #define NON_PMD_CORE_ID LCORE_ID_ANY > > -int dpdk_init(int argc, char **argv); > +void dpdk_init(const struct ovsrec_open_vswitch *ovs_cfg); > void netdev_dpdk_register(void); > void free_dpdk_buf(struct dp_packet *); > int pmd_thread_setaffinity_cpu(unsigned cpu); > @@ -33,13 +34,10 @@ int pmd_thread_setaffinity_cpu(unsigned cpu); > > #include "util.h" > > -static inline int > -dpdk_init(int argc, char **argv) > +static inline void > +dpdk_init(const struct ovsrec_open_vswitch *ovs_cfg OVS_UNUSED) > { > - if (argc >= 2 && !strcmp(argv[1], "--dpdk")) { > - ovs_fatal(0, "DPDK support not built into this copy of Open > vSwitch."); > - } > - return 0; > + > } > Why to remove this error handling? > > static inline void > diff --git a/utilities/ovs-ctl.in b/utilities/ovs-ctl.in > index 0082bed..6ae8bbd 100755 > --- a/utilities/ovs-ctl.in > +++ b/utilities/ovs-ctl.in > @@ -73,13 +73,13 @@ insert_mod_if_required () { > } > > ovs_vsctl () { > - ovs-vsctl --no-wait "$@" > + @bindir@/ovs-vsctl --no-wait "$@" > } > > set_system_ids () { > set ovs_vsctl set Open_vSwitch . > > - OVS_VERSION=`ovs-vswitchd --version | sed 's/.*) //;1q'` > + OVS_VERSION=`@bindir@/ovs-vswitchd --version | sed 's/.*) //;1q'` > set "$@" ovs-version="$OVS_VERSION" > > case $SYSTEM_ID in > @@ -131,7 +131,7 @@ check_force_cores () { > } > > del_transient_ports () { > - for port in `ovs-vsctl --bare -- --columns=name find port > other_config:transient=true`; do > + for port in `@bindir@/ovs-vsctl --bare -- --columns=name find port > other_config:transient=true`; do > ovs_vsctl -- del-port "$port" > done > } > @@ -193,7 +193,7 @@ add_managers () { > # won't briefly see empty datapath-id or ofport columns for records > that > # exist at startup.) > action "Enabling remote OVSDB managers" \ > - ovs-appctl -t ovsdb-server ovsdb-server/add-remote \ > + @bindir@/ovs-appctl -t ovsdb-server ovsdb-server/add-remote \ > db:Open_vSwitch,Open_vSwitch,manager_options > } > > @@ -215,7 +215,7 @@ start_forwarding () { > fi > > # Start ovs-vswitchd. > - set ovs-vswitchd unix:"$DB_SOCK" > + set @bindir@/ovs-vswitchd unix:"$DB_SOCK" > set "$@" -vconsole:emer -vsyslog:err -vfile:info > if test X"$MLOCKALL" != Xno; then > set "$@" --mlockall > @@ -276,7 +276,7 @@ save_ofports_if_required () { > # > # (Versions 1.10 and later save OpenFlow port numbers without > assistance, > # so we don't have to do anything for them. > - case `ovs-appctl version | sed 1q` in > + case `@bindir@/ovs-appctl version | sed 1q` in > "ovs-vswitchd (Open vSwitch) 1."[0-9].*) > action "Saving ofport values" ovs_save save-ofports \ > "${script_ofports}" > diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c > index b966d92..d33f42c 100644 > --- a/vswitchd/bridge.c > +++ b/vswitchd/bridge.c > @@ -68,6 +68,7 @@ > #include "sflow_api.h" > #include "vlan-bitmap.h" > #include "packets.h" > +#include "lib/netdev-dpdk.h" > > VLOG_DEFINE_THIS_MODULE(bridge); > > @@ -2921,6 +2922,8 @@ bridge_run(void) > } > cfg = ovsrec_open_vswitch_first(idl); > > + dpdk_init(cfg); > + > /* Initialize the ofproto library. This only needs to run once, but > * it must be done after the configuration is set. If the > * initialization has already occurred, bridge_init_ofproto() > diff --git a/vswitchd/ovs-vswitchd.c b/vswitchd/ovs-vswitchd.c > index e78ecda..ae86861 100644 > --- a/vswitchd/ovs-vswitchd.c > +++ b/vswitchd/ovs-vswitchd.c > @@ -48,7 +48,6 @@ > #include "openvswitch/vconn.h" > #include "openvswitch/vlog.h" > #include "lib/vswitch-idl.h" > -#include "lib/netdev-dpdk.h" > > VLOG_DEFINE_THIS_MODULE(vswitchd); > > @@ -71,13 +70,6 @@ main(int argc, char *argv[]) > int retval; > > set_program_name(argv[0]); > - retval = dpdk_init(argc,argv); > - if (retval < 0) { > - return retval; > - } > - > - argc -= retval; > - argv += retval; > > ovs_cmdl_proctitle_init(argc, argv); > service_start(&argc, &argv); > @@ -152,7 +144,6 @@ parse_options(int argc, char *argv[], char > **unixctl_pathp) > OPT_ENABLE_DUMMY, > OPT_DISABLE_SYSTEM, > DAEMON_OPTION_ENUMS, > - OPT_DPDK, > }; > static const struct option long_options[] = { > {"help", no_argument, NULL, 'h'}, > @@ -166,7 +157,6 @@ parse_options(int argc, char *argv[], char > **unixctl_pathp) > {"bootstrap-ca-cert", required_argument, NULL, > OPT_BOOTSTRAP_CA_CERT}, > {"enable-dummy", optional_argument, NULL, OPT_ENABLE_DUMMY}, > {"disable-system", no_argument, NULL, OPT_DISABLE_SYSTEM}, > - {"dpdk", required_argument, NULL, OPT_DPDK}, > {NULL, 0, NULL, 0}, > }; > char *short_options = > ovs_cmdl_long_options_to_short_options(long_options); > @@ -218,10 +208,6 @@ parse_options(int argc, char *argv[], char > **unixctl_pathp) > case '?': > exit(EXIT_FAILURE); > > - case OPT_DPDK: > - ovs_fatal(0, "--dpdk must be given at beginning of command > line."); > - break; > - > default: > abort(); > } > @@ -255,19 +241,6 @@ usage(void) > stream_usage("DATABASE", true, false, true); > daemon_usage(); > vlog_usage(); > - printf("\nDPDK options:\n" > - " --dpdk [VHOST] [DPDK] Initialize DPDK datapath.\n" > - " where DPDK are options for initializing DPDK lib and VHOST > is\n" > -#ifdef VHOST_CUSE > - " option to override default character device name used for\n" > - " for use with userspace vHost\n" > - " -cuse_dev_name NAME\n" > -#else > - " option to override default directory where vhost-user\n" > - " sockets are created.\n" > - " -vhost_sock_dir DIR\n" > -#endif > - ); > printf("\nOther options:\n" > " --unixctl=SOCKET override default control socket > name\n" > " -h, --help display this help message\n" > -- > 2.6.1.133.gf5b6079 > > _______________________________________________ > dev mailing list > dev@openvswitch.org > http://openvswitch.org/mailman/listinfo/dev > _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev