@@ -30,19 +30,33 @@
void
dummy_enable(const char *arg)
{
- enum dummy_level level;
+ enum dummy_level level = DUMMY_OVERRIDE_NONE;
+ enum dummy_type type = DUMMY_NON_PMD;
+ const char *s = arg;
- if (!arg || !arg[0]) {
- level = DUMMY_OVERRIDE_NONE;
- } else if (!strcmp(arg, "system")) {
- level = DUMMY_OVERRIDE_SYSTEM;
- } else if (!strcmp(arg, "override")) {
- level = DUMMY_OVERRIDE_ALL;
- } else {
- ovs_fatal(0, "%s: unknown dummy level", arg);
+ while (s && s[0]) {
+ size_t d = strcspn(s, ", \t\r\n");
+
+ if (!d) {
+ s++;
+ continue;
+ }
+
+ if (!strncmp(arg, "system", d)) {
+ level = DUMMY_OVERRIDE_SYSTEM;
+ } else if (!strncmp(arg, "override", d)) {
+ level = DUMMY_OVERRIDE_ALL;
+ } else if (!strncmp(arg, "pmd", d)) {
+ type = DUMMY_PMD;
+ } else if (!strncmp(arg, "non-pmd", d)) {
+ type = DUMMY_NON_PMD;
+ } else {
+ ovs_fatal(0, "%s: unknown dummy option", arg);
+ }
+ s += d;
}
- netdev_dummy_register(level);
+ netdev_dummy_register(level, type);
dpif_dummy_register(level);
timeval_dummy_register();
vlandev_dummy_enable();
@@ -30,12 +30,18 @@ enum dummy_level {
DUMMY_OVERRIDE_ALL, /* Replace all types by dummy. */
};
+/* Type of dummy inreface. */
+enum dummy_type {
+ DUMMY_NON_PMD, /* Use non-PMD dummy class. */
+ DUMMY_PMD, /* Force using PMD dummy class. */
+};
+
/* For client programs to call directly to enable dummy support. */
void dummy_enable(const char *arg);
/* Implementation details. */
void dpif_dummy_register(enum dummy_level);
-void netdev_dummy_register(enum dummy_level);
+void netdev_dummy_register(enum dummy_level, enum dummy_type);
void timeval_dummy_register(void);
void vlandev_dummy_enable(void);
void ofpact_dummy_enable(void);
@@ -806,6 +806,12 @@ netdev_dummy_set_config(struct netdev *netdev_, const struct smap *args)
return 0;
}
+static int
+netdev_dummy_get_numa_id(const struct netdev *netdev_ OVS_UNUSED)
+{
+ return 0;
+}
+
static struct netdev_rxq *
netdev_dummy_rxq_alloc(void)
{
@@ -1193,74 +1199,78 @@ netdev_dummy_update_flags(struct netdev *netdev_,
/* Helper functions. */
-static const struct netdev_class dummy_class = {
- "dummy",
- false, /* is_pmd */
- NULL, /* init */
- netdev_dummy_run,
- netdev_dummy_wait,
-
- netdev_dummy_alloc,
- netdev_dummy_construct,
- netdev_dummy_destruct,
- netdev_dummy_dealloc,
- netdev_dummy_get_config,
- netdev_dummy_set_config,
- NULL, /* get_tunnel_config */
- NULL, /* build header */
- NULL, /* push header */
- NULL, /* pop header */
- NULL, /* get_numa_id */
- NULL, /* set_multiq */
-
- netdev_dummy_send, /* send */
- NULL, /* send_wait */
-
- netdev_dummy_set_etheraddr,
- netdev_dummy_get_etheraddr,
- netdev_dummy_get_mtu,
- netdev_dummy_set_mtu,
- netdev_dummy_get_ifindex,
- NULL, /* get_carrier */
- NULL, /* get_carrier_resets */
- NULL, /* get_miimon */
- netdev_dummy_get_stats,
-
- NULL, /* get_features */
- NULL, /* set_advertisements */
-
- NULL, /* set_policing */
- NULL, /* get_qos_types */
- NULL, /* get_qos_capabilities */
- NULL, /* get_qos */
- NULL, /* set_qos */
- netdev_dummy_get_queue,
- NULL, /* set_queue */
- NULL, /* delete_queue */
- netdev_dummy_get_queue_stats,
- netdev_dummy_queue_dump_start,
- netdev_dummy_queue_dump_next,
- netdev_dummy_queue_dump_done,
- netdev_dummy_dump_queue_stats,
-
- netdev_dummy_get_in4, /* get_in4 */
- NULL, /* set_in4 */
- netdev_dummy_get_in6, /* get_in6 */
- NULL, /* add_router */
- NULL, /* get_next_hop */
- NULL, /* get_status */
- NULL, /* arp_lookup */
-
- netdev_dummy_update_flags,
-
- netdev_dummy_rxq_alloc,
- netdev_dummy_rxq_construct,
- netdev_dummy_rxq_destruct,
- netdev_dummy_rxq_dealloc,
- netdev_dummy_rxq_recv,
- netdev_dummy_rxq_wait,
- netdev_dummy_rxq_drain,
-};
+#define NETDEV_DUMMY_CLASS(PMD) \
+{ \
+ "dummy", \
+ PMD, /* is_pmd */ \
+ NULL, /* init */ \
+ netdev_dummy_run, \
+ netdev_dummy_wait, \
+ \
+ netdev_dummy_alloc, \
+ netdev_dummy_construct, \
+ netdev_dummy_destruct, \
+ netdev_dummy_dealloc, \
+ netdev_dummy_get_config, \
+ netdev_dummy_set_config, \
+ NULL, /* get_tunnel_config */ \
+ NULL, /* build header */ \
+ NULL, /* push header */ \
+ NULL, /* pop header */ \
+ netdev_dummy_get_numa_id, \
+ NULL, /* set_multiq */ \
+ \
+ netdev_dummy_send, /* send */ \
+ NULL, /* send_wait */ \
+ \
+ netdev_dummy_set_etheraddr, \
+ netdev_dummy_get_etheraddr, \
+ netdev_dummy_get_mtu, \
+ netdev_dummy_set_mtu, \
+ netdev_dummy_get_ifindex, \
+ NULL, /* get_carrier */ \
+ NULL, /* get_carrier_resets */ \
+ NULL, /* get_miimon */ \
+ netdev_dummy_get_stats, \
+ \
+ NULL, /* get_features */ \
+ NULL, /* set_advertisements */ \
+ \
+ NULL, /* set_policing */ \
+ NULL, /* get_qos_types */ \
+ NULL, /* get_qos_capabilities */ \
+ NULL, /* get_qos */ \
+ NULL, /* set_qos */ \
+ netdev_dummy_get_queue, \
+ NULL, /* set_queue */ \
+ NULL, /* delete_queue */ \
+ netdev_dummy_get_queue_stats, \
+ netdev_dummy_queue_dump_start, \
+ netdev_dummy_queue_dump_next, \
+ netdev_dummy_queue_dump_done, \
+ netdev_dummy_dump_queue_stats, \
+ \
+ netdev_dummy_get_in4, /* get_in4 */ \
+ NULL, /* set_in4 */ \
+ netdev_dummy_get_in6, /* get_in6 */ \
+ NULL, /* add_router */ \
+ NULL, /* get_next_hop */ \
+ NULL, /* get_status */ \
+ NULL, /* arp_lookup */ \
+ \
+ netdev_dummy_update_flags, \
+ \
+ netdev_dummy_rxq_alloc, \
+ netdev_dummy_rxq_construct, \
+ netdev_dummy_rxq_destruct, \
+ netdev_dummy_rxq_dealloc, \
+ netdev_dummy_rxq_recv, \
+ netdev_dummy_rxq_wait, \
+ netdev_dummy_rxq_drain, \
+}
+
+static const struct netdev_class dummy_class = NETDEV_DUMMY_CLASS(false);
+static const struct netdev_class dummy_pmd_class = NETDEV_DUMMY_CLASS(true);
static void
pkt_list_delete(struct ovs_list *l)
@@ -1558,13 +1568,17 @@ netdev_dummy_ip6addr(struct unixctl_conn *conn, int argc OVS_UNUSED,
static void
-netdev_dummy_override(const char *type)
+netdev_dummy_override(const char *type, enum dummy_type dummy_type)
{
if (!netdev_unregister_provider(type)) {
struct netdev_class *class;
int error;
- class = xmemdup(&dummy_class, sizeof dummy_class);
+ if (dummy_type == DUMMY_NON_PMD) {
+ class = xmemdup(&dummy_class, sizeof dummy_class);
+ } else {
+ class = xmemdup(&dummy_pmd_class, sizeof dummy_pmd_class);
+ }
class->type = xstrdup(type);
error = netdev_register_provider(class);
if (error) {
@@ -1577,7 +1591,7 @@ netdev_dummy_override(const char *type)
}
void
-netdev_dummy_register(enum dummy_level level)
+netdev_dummy_register(enum dummy_level level, enum dummy_type dummy_type)
{
unixctl_command_register("netdev-dummy/receive", "name packet|flow...",
2, INT_MAX, netdev_dummy_receive, NULL);
@@ -1602,14 +1616,19 @@ netdev_dummy_register(enum dummy_level level)
netdev_enumerate_types(&types);
SSET_FOR_EACH (type, &types) {
if (strcmp(type, "patch")) {
- netdev_dummy_override(type);
+ netdev_dummy_override(type, dummy_type);
}
}
sset_destroy(&types);
} else if (level == DUMMY_OVERRIDE_SYSTEM) {
- netdev_dummy_override("system");
+ netdev_dummy_override("system", dummy_type);
+ }
+
+ if (dummy_type == DUMMY_NON_PMD) {
+ netdev_register_provider(&dummy_class);
+ } else {
+ netdev_register_provider(&dummy_pmd_class);
}
- netdev_register_provider(&dummy_class);
netdev_vport_tunnel_register();
}
'dummy_pmd' class is a replacement for 'dummy' class. Created in purposes of testing of PMD interfaces. May be activated instead of usual 'dummy' by additional parameter 'pmd' to --enable-dummy. Ex.: ovs-vswitchd --enable-dummy=pmd or ovs-vswitchd --enable-dummy=override,pmd Name of 'dummy_pmd' class is "dummy". So, all ports should be added as usual: ovs-vswitchd set interface <iface> type=dummy Signed-off-by: Ilya Maximets <i.maximets@samsung.com> --- lib/dummy.c | 34 +++++++---- lib/dummy.h | 8 ++- lib/netdev-dummy.c | 167 +++++++++++++++++++++++++++++------------------------ 3 files changed, 124 insertions(+), 85 deletions(-)