qmp/hmp: add rocker device support
Add QMP/HMP support for rocker devices. This is mostly for debugging purposes to see inside the device's tables and port configurations. Some examples: (qemu) info rocker sw1 name: sw1 id: 0x0000013512005452 ports: 4 (qemu) info rocker-ports sw1 ena/ speed/ auto port link duplex neg? sw1.1 up 10G FD No sw1.2 up 10G FD No sw1.3 !ena 10G FD No sw1.4 !ena 10G FD No (qemu) info rocker-of-dpa-flows sw1 prio tbl hits key(mask) --> actions 2 60 pport 1 vlan 1 LLDP src 00:02:00:00:02:00 dst 01:80:c2:00:00:0e 2 60 pport 1 vlan 1 ARP src 00:02:00:00:02:00 dst 00:02:00:00:03:00 2 60 pport 2 vlan 2 IPv6 src 00:02:00:00:03:00 dst 33:33:ff:00:00:02 proto 58 3 50 vlan 2 dst 33:33:ff:00:00:02 --> write group 0x32000001 goto tbl 60 2 60 pport 2 vlan 2 IPv6 src 00:02:00:00:03:00 dst 33:33:ff:00:03:00 proto 58 3 50 1 vlan 2 dst 33:33:ff:00:03:00 --> write group 0x32000001 goto tbl 60 2 60 pport 2 vlan 2 ARP src 00:02:00:00:03:00 dst 00:02:00:00:02:00 3 50 2 vlan 2 dst 00:02:00:00:02:00 --> write group 0x02000001 goto tbl 60 2 60 1 pport 2 vlan 2 IP src 00:02:00:00:03:00 dst 00:02:00:00:02:00 proto 1 3 50 2 vlan 1 dst 00:02:00:00:03:00 --> write group 0x01000002 goto tbl 60 2 60 1 pport 1 vlan 1 IP src 00:02:00:00:02:00 dst 00:02:00:00:03:00 proto 1 2 60 pport 1 vlan 1 IPv6 src 00:02:00:00:02:00 dst 33:33:ff:00:00:01 proto 58 3 50 vlan 1 dst 33:33:ff:00:00:01 --> write group 0x31000000 goto tbl 60 2 60 pport 1 vlan 1 IPv6 src 00:02:00:00:02:00 dst 33:33:ff:00:02:00 proto 58 3 50 1 vlan 1 dst 33:33:ff:00:02:00 --> write group 0x31000000 goto tbl 60 1 60 173 pport 2 vlan 2 LLDP src <any> dst 01:80:c2:00:00:0e --> write group 0x02000000 1 60 6 pport 2 vlan 2 IPv6 src <any> dst <any> --> write group 0x02000000 1 60 174 pport 1 vlan 1 LLDP src <any> dst 01:80:c2:00:00:0e --> write group 0x01000000 1 60 174 pport 2 vlan 2 IP src <any> dst <any> --> write group 0x02000000 1 60 6 pport 1 vlan 1 IPv6 src <any> dst <any> --> write group 0x01000000 1 60 181 pport 2 vlan 2 ARP src <any> dst <any> --> write group 0x02000000 1 10 715 pport 2 --> apply new vlan 2 goto tbl 20 1 60 177 pport 1 vlan 1 ARP src <any> dst <any> --> write group 0x01000000 1 60 174 pport 1 vlan 1 IP src <any> dst <any> --> write group 0x01000000 1 10 717 pport 1 --> apply new vlan 1 goto tbl 20 1 0 1432 pport 0(0xffff) --> goto tbl 10 (qemu) info rocker-of-dpa-groups sw1 id (decode) --> buckets 0x32000001 (type L2 multicast vlan 2 index 1) --> groups [0x02000001,0x02000000] 0x02000001 (type L2 interface vlan 2 pport 1) --> pop vlan out pport 1 0x01000002 (type L2 interface vlan 1 pport 2) --> pop vlan out pport 2 0x02000000 (type L2 interface vlan 2 pport 0) --> pop vlan out pport 0 0x01000000 (type L2 interface vlan 1 pport 0) --> pop vlan out pport 0 0x31000000 (type L2 multicast vlan 1 index 0) --> groups [0x01000002,0x01000000] [Added "query-" prefixes to rocker.json commands as suggested by Eric Blake <eblake@redhat.com>. --Stefan] Signed-off-by: Scott Feldman <sfeldma@gmail.com> Signed-off-by: Jiri Pirko <jiri@resnulli.us> Message-id: 1433985681-56138-5-git-send-email-sfeldma@gmail.com Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
parent
5ff1547b75
commit
fafa4d508b
@ -1798,6 +1798,30 @@ STEXI
|
||||
show available trace events and their state
|
||||
ETEXI
|
||||
|
||||
STEXI
|
||||
@item rocker @var{name}
|
||||
@findex rocker
|
||||
Show Rocker(s)
|
||||
ETEXI
|
||||
|
||||
STEXI
|
||||
@item rocker_ports @var{name}
|
||||
@findex rocker_ports
|
||||
Show Rocker ports
|
||||
ETEXI
|
||||
|
||||
STEXI
|
||||
@item rocker_of_dpa_flows @var{name} [@var{tbl_id}]
|
||||
@findex rocker_of_dpa_flows
|
||||
Show Rocker OF-DPA flow tables
|
||||
ETEXI
|
||||
|
||||
STEXI
|
||||
@item rocker_of_dpa_groups @var{name} [@var{type}]
|
||||
@findex rocker_of_dpa_groups
|
||||
Show Rocker OF-DPA groups
|
||||
ETEXI
|
||||
|
||||
STEXI
|
||||
@end table
|
||||
ETEXI
|
||||
|
303
hmp.c
303
hmp.c
@ -15,6 +15,7 @@
|
||||
|
||||
#include "hmp.h"
|
||||
#include "net/net.h"
|
||||
#include "net/eth.h"
|
||||
#include "sysemu/char.h"
|
||||
#include "sysemu/block-backend.h"
|
||||
#include "qemu/option.h"
|
||||
@ -1999,3 +2000,305 @@ void hmp_qom_set(Monitor *mon, const QDict *qdict)
|
||||
}
|
||||
hmp_handle_error(mon, &err);
|
||||
}
|
||||
|
||||
void hmp_rocker(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
const char *name = qdict_get_str(qdict, "name");
|
||||
RockerSwitch *rocker;
|
||||
Error *errp = NULL;
|
||||
|
||||
rocker = qmp_query_rocker(name, &errp);
|
||||
if (errp != NULL) {
|
||||
hmp_handle_error(mon, &errp);
|
||||
return;
|
||||
}
|
||||
|
||||
monitor_printf(mon, "name: %s\n", rocker->name);
|
||||
monitor_printf(mon, "id: 0x%" PRIx64 "\n", rocker->id);
|
||||
monitor_printf(mon, "ports: %d\n", rocker->ports);
|
||||
|
||||
qapi_free_RockerSwitch(rocker);
|
||||
}
|
||||
|
||||
void hmp_rocker_ports(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
RockerPortList *list, *port;
|
||||
const char *name = qdict_get_str(qdict, "name");
|
||||
Error *errp = NULL;
|
||||
|
||||
list = qmp_query_rocker_ports(name, &errp);
|
||||
if (errp != NULL) {
|
||||
hmp_handle_error(mon, &errp);
|
||||
return;
|
||||
}
|
||||
|
||||
monitor_printf(mon, " ena/ speed/ auto\n");
|
||||
monitor_printf(mon, " port link duplex neg?\n");
|
||||
|
||||
for (port = list; port; port = port->next) {
|
||||
monitor_printf(mon, "%10s %-4s %-3s %2s %-3s\n",
|
||||
port->value->name,
|
||||
port->value->enabled ? port->value->link_up ?
|
||||
"up" : "down" : "!ena",
|
||||
port->value->speed == 10000 ? "10G" : "??",
|
||||
port->value->duplex ? "FD" : "HD",
|
||||
port->value->autoneg ? "Yes" : "No");
|
||||
}
|
||||
|
||||
qapi_free_RockerPortList(list);
|
||||
}
|
||||
|
||||
void hmp_rocker_of_dpa_flows(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
RockerOfDpaFlowList *list, *info;
|
||||
const char *name = qdict_get_str(qdict, "name");
|
||||
uint32_t tbl_id = qdict_get_try_int(qdict, "tbl_id", -1);
|
||||
Error *errp = NULL;
|
||||
|
||||
list = qmp_query_rocker_of_dpa_flows(name, tbl_id != -1, tbl_id, &errp);
|
||||
if (errp != NULL) {
|
||||
hmp_handle_error(mon, &errp);
|
||||
return;
|
||||
}
|
||||
|
||||
monitor_printf(mon, "prio tbl hits key(mask) --> actions\n");
|
||||
|
||||
for (info = list; info; info = info->next) {
|
||||
RockerOfDpaFlow *flow = info->value;
|
||||
RockerOfDpaFlowKey *key = flow->key;
|
||||
RockerOfDpaFlowMask *mask = flow->mask;
|
||||
RockerOfDpaFlowAction *action = flow->action;
|
||||
|
||||
if (flow->hits) {
|
||||
monitor_printf(mon, "%-4d %-3d %-4" PRIu64,
|
||||
key->priority, key->tbl_id, flow->hits);
|
||||
} else {
|
||||
monitor_printf(mon, "%-4d %-3d ",
|
||||
key->priority, key->tbl_id);
|
||||
}
|
||||
|
||||
if (key->has_in_pport) {
|
||||
monitor_printf(mon, " pport %d", key->in_pport);
|
||||
if (mask->has_in_pport) {
|
||||
monitor_printf(mon, "(0x%x)", mask->in_pport);
|
||||
}
|
||||
}
|
||||
|
||||
if (key->has_vlan_id) {
|
||||
monitor_printf(mon, " vlan %d",
|
||||
key->vlan_id & VLAN_VID_MASK);
|
||||
if (mask->has_vlan_id) {
|
||||
monitor_printf(mon, "(0x%x)", mask->vlan_id);
|
||||
}
|
||||
}
|
||||
|
||||
if (key->has_tunnel_id) {
|
||||
monitor_printf(mon, " tunnel %d", key->tunnel_id);
|
||||
if (mask->has_tunnel_id) {
|
||||
monitor_printf(mon, "(0x%x)", mask->tunnel_id);
|
||||
}
|
||||
}
|
||||
|
||||
if (key->has_eth_type) {
|
||||
switch (key->eth_type) {
|
||||
case 0x0806:
|
||||
monitor_printf(mon, " ARP");
|
||||
break;
|
||||
case 0x0800:
|
||||
monitor_printf(mon, " IP");
|
||||
break;
|
||||
case 0x86dd:
|
||||
monitor_printf(mon, " IPv6");
|
||||
break;
|
||||
case 0x8809:
|
||||
monitor_printf(mon, " LACP");
|
||||
break;
|
||||
case 0x88cc:
|
||||
monitor_printf(mon, " LLDP");
|
||||
break;
|
||||
default:
|
||||
monitor_printf(mon, " eth type 0x%04x", key->eth_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (key->has_eth_src) {
|
||||
if ((strcmp(key->eth_src, "01:00:00:00:00:00") == 0) &&
|
||||
(mask->has_eth_src) &&
|
||||
(strcmp(mask->eth_src, "01:00:00:00:00:00") == 0)) {
|
||||
monitor_printf(mon, " src <any mcast/bcast>");
|
||||
} else if ((strcmp(key->eth_src, "00:00:00:00:00:00") == 0) &&
|
||||
(mask->has_eth_src) &&
|
||||
(strcmp(mask->eth_src, "01:00:00:00:00:00") == 0)) {
|
||||
monitor_printf(mon, " src <any ucast>");
|
||||
} else {
|
||||
monitor_printf(mon, " src %s", key->eth_src);
|
||||
if (mask->has_eth_src) {
|
||||
monitor_printf(mon, "(%s)", mask->eth_src);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (key->has_eth_dst) {
|
||||
if ((strcmp(key->eth_dst, "01:00:00:00:00:00") == 0) &&
|
||||
(mask->has_eth_dst) &&
|
||||
(strcmp(mask->eth_dst, "01:00:00:00:00:00") == 0)) {
|
||||
monitor_printf(mon, " dst <any mcast/bcast>");
|
||||
} else if ((strcmp(key->eth_dst, "00:00:00:00:00:00") == 0) &&
|
||||
(mask->has_eth_dst) &&
|
||||
(strcmp(mask->eth_dst, "01:00:00:00:00:00") == 0)) {
|
||||
monitor_printf(mon, " dst <any ucast>");
|
||||
} else {
|
||||
monitor_printf(mon, " dst %s", key->eth_dst);
|
||||
if (mask->has_eth_dst) {
|
||||
monitor_printf(mon, "(%s)", mask->eth_dst);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (key->has_ip_proto) {
|
||||
monitor_printf(mon, " proto %d", key->ip_proto);
|
||||
if (mask->has_ip_proto) {
|
||||
monitor_printf(mon, "(0x%x)", mask->ip_proto);
|
||||
}
|
||||
}
|
||||
|
||||
if (key->has_ip_tos) {
|
||||
monitor_printf(mon, " TOS %d", key->ip_tos);
|
||||
if (mask->has_ip_tos) {
|
||||
monitor_printf(mon, "(0x%x)", mask->ip_tos);
|
||||
}
|
||||
}
|
||||
|
||||
if (key->has_ip_dst) {
|
||||
monitor_printf(mon, " dst %s", key->ip_dst);
|
||||
}
|
||||
|
||||
if (action->has_goto_tbl || action->has_group_id ||
|
||||
action->has_new_vlan_id) {
|
||||
monitor_printf(mon, " -->");
|
||||
}
|
||||
|
||||
if (action->has_new_vlan_id) {
|
||||
monitor_printf(mon, " apply new vlan %d",
|
||||
ntohs(action->new_vlan_id));
|
||||
}
|
||||
|
||||
if (action->has_group_id) {
|
||||
monitor_printf(mon, " write group 0x%08x", action->group_id);
|
||||
}
|
||||
|
||||
if (action->has_goto_tbl) {
|
||||
monitor_printf(mon, " goto tbl %d", action->goto_tbl);
|
||||
}
|
||||
|
||||
monitor_printf(mon, "\n");
|
||||
}
|
||||
|
||||
qapi_free_RockerOfDpaFlowList(list);
|
||||
}
|
||||
|
||||
void hmp_rocker_of_dpa_groups(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
RockerOfDpaGroupList *list, *g;
|
||||
const char *name = qdict_get_str(qdict, "name");
|
||||
uint8_t type = qdict_get_try_int(qdict, "type", 9);
|
||||
Error *errp = NULL;
|
||||
bool set = false;
|
||||
|
||||
list = qmp_query_rocker_of_dpa_groups(name, type != 9, type, &errp);
|
||||
if (errp != NULL) {
|
||||
hmp_handle_error(mon, &errp);
|
||||
return;
|
||||
}
|
||||
|
||||
monitor_printf(mon, "id (decode) --> buckets\n");
|
||||
|
||||
for (g = list; g; g = g->next) {
|
||||
RockerOfDpaGroup *group = g->value;
|
||||
|
||||
monitor_printf(mon, "0x%08x", group->id);
|
||||
|
||||
monitor_printf(mon, " (type %s", group->type == 0 ? "L2 interface" :
|
||||
group->type == 1 ? "L2 rewrite" :
|
||||
group->type == 2 ? "L3 unicast" :
|
||||
group->type == 3 ? "L2 multicast" :
|
||||
group->type == 4 ? "L2 flood" :
|
||||
group->type == 5 ? "L3 interface" :
|
||||
group->type == 6 ? "L3 multicast" :
|
||||
group->type == 7 ? "L3 ECMP" :
|
||||
group->type == 8 ? "L2 overlay" :
|
||||
"unknown");
|
||||
|
||||
if (group->has_vlan_id) {
|
||||
monitor_printf(mon, " vlan %d", group->vlan_id);
|
||||
}
|
||||
|
||||
if (group->has_pport) {
|
||||
monitor_printf(mon, " pport %d", group->pport);
|
||||
}
|
||||
|
||||
if (group->has_index) {
|
||||
monitor_printf(mon, " index %d", group->index);
|
||||
}
|
||||
|
||||
monitor_printf(mon, ") -->");
|
||||
|
||||
if (group->has_set_vlan_id && group->set_vlan_id) {
|
||||
set = true;
|
||||
monitor_printf(mon, " set vlan %d",
|
||||
group->set_vlan_id & VLAN_VID_MASK);
|
||||
}
|
||||
|
||||
if (group->has_set_eth_src) {
|
||||
if (!set) {
|
||||
set = true;
|
||||
monitor_printf(mon, " set");
|
||||
}
|
||||
monitor_printf(mon, " src %s", group->set_eth_src);
|
||||
}
|
||||
|
||||
if (group->has_set_eth_dst) {
|
||||
if (!set) {
|
||||
set = true;
|
||||
monitor_printf(mon, " set");
|
||||
}
|
||||
monitor_printf(mon, " dst %s", group->set_eth_dst);
|
||||
}
|
||||
|
||||
set = false;
|
||||
|
||||
if (group->has_ttl_check && group->ttl_check) {
|
||||
monitor_printf(mon, " check TTL");
|
||||
}
|
||||
|
||||
if (group->has_group_id && group->group_id) {
|
||||
monitor_printf(mon, " group id 0x%08x", group->group_id);
|
||||
}
|
||||
|
||||
if (group->has_pop_vlan && group->pop_vlan) {
|
||||
monitor_printf(mon, " pop vlan");
|
||||
}
|
||||
|
||||
if (group->has_out_pport) {
|
||||
monitor_printf(mon, " out pport %d", group->out_pport);
|
||||
}
|
||||
|
||||
if (group->has_group_ids) {
|
||||
struct uint32List *id;
|
||||
|
||||
monitor_printf(mon, " groups [");
|
||||
for (id = group->group_ids; id; id = id->next) {
|
||||
monitor_printf(mon, "0x%08x", id->value);
|
||||
if (id->next) {
|
||||
monitor_printf(mon, ",");
|
||||
}
|
||||
}
|
||||
monitor_printf(mon, "]");
|
||||
}
|
||||
|
||||
monitor_printf(mon, "\n");
|
||||
}
|
||||
|
||||
qapi_free_RockerOfDpaGroupList(list);
|
||||
}
|
||||
|
4
hmp.h
4
hmp.h
@ -124,5 +124,9 @@ void host_net_remove_completion(ReadLineState *rs, int nb_args,
|
||||
const char *str);
|
||||
void delvm_completion(ReadLineState *rs, int nb_args, const char *str);
|
||||
void loadvm_completion(ReadLineState *rs, int nb_args, const char *str);
|
||||
void hmp_rocker(Monitor *mon, const QDict *qdict);
|
||||
void hmp_rocker_ports(Monitor *mon, const QDict *qdict);
|
||||
void hmp_rocker_of_dpa_flows(Monitor *mon, const QDict *qdict);
|
||||
void hmp_rocker_of_dpa_groups(Monitor *mon, const QDict *qdict);
|
||||
|
||||
#endif
|
||||
|
@ -39,3 +39,4 @@ obj-$(CONFIG_ETSEC) += fsl_etsec/etsec.o fsl_etsec/registers.o \
|
||||
common-obj-$(CONFIG_ROCKER) += rocker/rocker.o rocker/rocker_fp.o \
|
||||
rocker/rocker_desc.o rocker/rocker_world.o \
|
||||
rocker/rocker_of_dpa.o
|
||||
obj-$(call lnot,$(CONFIG_ROCKER)) += rocker/qmp-norocker.o
|
||||
|
50
hw/net/rocker/qmp-norocker.c
Normal file
50
hw/net/rocker/qmp-norocker.c
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* QMP Target options - Commands handled based on a target config
|
||||
* versus a host config
|
||||
*
|
||||
* Copyright (c) 2015 David Ahern <dsahern@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "qemu-common.h"
|
||||
#include "qmp-commands.h"
|
||||
#include "qapi/qmp/qerror.h"
|
||||
|
||||
RockerSwitch *qmp_query_rocker(const char *name, Error **errp)
|
||||
{
|
||||
error_set(errp, QERR_FEATURE_DISABLED, "rocker");
|
||||
return NULL;
|
||||
};
|
||||
|
||||
RockerPortList *qmp_query_rocker_ports(const char *name, Error **errp)
|
||||
{
|
||||
error_set(errp, QERR_FEATURE_DISABLED, "rocker");
|
||||
return NULL;
|
||||
};
|
||||
|
||||
RockerOfDpaFlowList *qmp_query_rocker_of_dpa_flows(const char *name,
|
||||
bool has_tbl_id,
|
||||
uint32_t tbl_id,
|
||||
Error **errp)
|
||||
{
|
||||
error_set(errp, QERR_FEATURE_DISABLED, "rocker");
|
||||
return NULL;
|
||||
};
|
||||
|
||||
RockerOfDpaGroupList *qmp_query_rocker_of_dpa_groups(const char *name,
|
||||
bool has_type,
|
||||
uint8_t type,
|
||||
Error **errp)
|
||||
{
|
||||
error_set(errp, QERR_FEATURE_DISABLED, "rocker");
|
||||
return NULL;
|
||||
};
|
@ -94,6 +94,51 @@ World *rocker_get_world(Rocker *r, enum rocker_world_type type)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RockerSwitch *qmp_query_rocker(const char *name, Error **errp)
|
||||
{
|
||||
RockerSwitch *rocker = g_malloc0(sizeof(*rocker));
|
||||
Rocker *r;
|
||||
|
||||
r = rocker_find(name);
|
||||
if (!r) {
|
||||
error_set(errp, ERROR_CLASS_GENERIC_ERROR,
|
||||
"rocker %s not found", name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rocker->name = g_strdup(r->name);
|
||||
rocker->id = r->switch_id;
|
||||
rocker->ports = r->fp_ports;
|
||||
|
||||
return rocker;
|
||||
}
|
||||
|
||||
RockerPortList *qmp_query_rocker_ports(const char *name, Error **errp)
|
||||
{
|
||||
RockerPortList *list = NULL;
|
||||
Rocker *r;
|
||||
int i;
|
||||
|
||||
r = rocker_find(name);
|
||||
if (!r) {
|
||||
error_set(errp, ERROR_CLASS_GENERIC_ERROR,
|
||||
"rocker %s not found", name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = r->fp_ports - 1; i >= 0; i--) {
|
||||
RockerPortList *info = g_malloc0(sizeof(*info));
|
||||
info->value = g_malloc0(sizeof(*info->value));
|
||||
struct fp_port *port = r->fp_port[i];
|
||||
|
||||
fp_port_get_info(port, info);
|
||||
info->next = list;
|
||||
list = info;
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
uint32_t rocker_fp_ports(Rocker *r)
|
||||
{
|
||||
return r->fp_ports;
|
||||
|
@ -51,6 +51,16 @@ bool fp_port_get_link_up(FpPort *port)
|
||||
return !qemu_get_queue(port->nic)->link_down;
|
||||
}
|
||||
|
||||
void fp_port_get_info(FpPort *port, RockerPortList *info)
|
||||
{
|
||||
info->value->name = g_strdup(port->name);
|
||||
info->value->enabled = port->enabled;
|
||||
info->value->link_up = fp_port_get_link_up(port);
|
||||
info->value->speed = port->speed;
|
||||
info->value->duplex = port->duplex;
|
||||
info->value->autoneg = port->autoneg;
|
||||
}
|
||||
|
||||
void fp_port_get_macaddr(FpPort *port, MACAddr *macaddr)
|
||||
{
|
||||
memcpy(macaddr->a, port->conf.macaddr.a, sizeof(macaddr->a));
|
||||
|
@ -28,6 +28,7 @@ int fp_port_eg(FpPort *port, const struct iovec *iov, int iovcnt);
|
||||
|
||||
char *fp_port_get_name(FpPort *port);
|
||||
bool fp_port_get_link_up(FpPort *port);
|
||||
void fp_port_get_info(FpPort *port, RockerPortList *info);
|
||||
void fp_port_get_macaddr(FpPort *port, MACAddr *macaddr);
|
||||
void fp_port_set_macaddr(FpPort *port, MACAddr *macaddr);
|
||||
uint8_t fp_port_get_learning(FpPort *port);
|
||||
|
@ -2302,6 +2302,318 @@ static void of_dpa_uninit(World *world)
|
||||
g_hash_table_destroy(of_dpa->flow_tbl);
|
||||
}
|
||||
|
||||
struct of_dpa_flow_fill_context {
|
||||
RockerOfDpaFlowList *list;
|
||||
uint32_t tbl_id;
|
||||
};
|
||||
|
||||
static void of_dpa_flow_fill(void *cookie, void *value, void *user_data)
|
||||
{
|
||||
struct of_dpa_flow *flow = value;
|
||||
struct of_dpa_flow_key *key = &flow->key;
|
||||
struct of_dpa_flow_key *mask = &flow->mask;
|
||||
struct of_dpa_flow_fill_context *flow_context = user_data;
|
||||
RockerOfDpaFlowList *new;
|
||||
RockerOfDpaFlow *nflow;
|
||||
RockerOfDpaFlowKey *nkey;
|
||||
RockerOfDpaFlowMask *nmask;
|
||||
RockerOfDpaFlowAction *naction;
|
||||
|
||||
if (flow_context->tbl_id != -1 &&
|
||||
flow_context->tbl_id != key->tbl_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
new = g_malloc0(sizeof(*new));
|
||||
nflow = new->value = g_malloc0(sizeof(*nflow));
|
||||
nkey = nflow->key = g_malloc0(sizeof(*nkey));
|
||||
nmask = nflow->mask = g_malloc0(sizeof(*nmask));
|
||||
naction = nflow->action = g_malloc0(sizeof(*naction));
|
||||
|
||||
nflow->cookie = flow->cookie;
|
||||
nflow->hits = flow->stats.hits;
|
||||
nkey->priority = flow->priority;
|
||||
nkey->tbl_id = key->tbl_id;
|
||||
|
||||
if (key->in_pport || mask->in_pport) {
|
||||
nkey->has_in_pport = true;
|
||||
nkey->in_pport = key->in_pport;
|
||||
}
|
||||
|
||||
if (nkey->has_in_pport && mask->in_pport != 0xffffffff) {
|
||||
nmask->has_in_pport = true;
|
||||
nmask->in_pport = mask->in_pport;
|
||||
}
|
||||
|
||||
if (key->eth.vlan_id || mask->eth.vlan_id) {
|
||||
nkey->has_vlan_id = true;
|
||||
nkey->vlan_id = ntohs(key->eth.vlan_id);
|
||||
}
|
||||
|
||||
if (nkey->has_vlan_id && mask->eth.vlan_id != 0xffff) {
|
||||
nmask->has_vlan_id = true;
|
||||
nmask->vlan_id = ntohs(mask->eth.vlan_id);
|
||||
}
|
||||
|
||||
if (key->tunnel_id || mask->tunnel_id) {
|
||||
nkey->has_tunnel_id = true;
|
||||
nkey->tunnel_id = key->tunnel_id;
|
||||
}
|
||||
|
||||
if (nkey->has_tunnel_id && mask->tunnel_id != 0xffffffff) {
|
||||
nmask->has_tunnel_id = true;
|
||||
nmask->tunnel_id = mask->tunnel_id;
|
||||
}
|
||||
|
||||
if (memcmp(key->eth.src.a, zero_mac.a, ETH_ALEN) ||
|
||||
memcmp(mask->eth.src.a, zero_mac.a, ETH_ALEN)) {
|
||||
nkey->has_eth_src = true;
|
||||
nkey->eth_src = qemu_mac_strdup_printf(key->eth.src.a);
|
||||
}
|
||||
|
||||
if (nkey->has_eth_src && memcmp(mask->eth.src.a, ff_mac.a, ETH_ALEN)) {
|
||||
nmask->has_eth_src = true;
|
||||
nmask->eth_src = qemu_mac_strdup_printf(mask->eth.src.a);
|
||||
}
|
||||
|
||||
if (memcmp(key->eth.dst.a, zero_mac.a, ETH_ALEN) ||
|
||||
memcmp(mask->eth.dst.a, zero_mac.a, ETH_ALEN)) {
|
||||
nkey->has_eth_dst = true;
|
||||
nkey->eth_dst = qemu_mac_strdup_printf(key->eth.dst.a);
|
||||
}
|
||||
|
||||
if (nkey->has_eth_dst && memcmp(mask->eth.dst.a, ff_mac.a, ETH_ALEN)) {
|
||||
nmask->has_eth_dst = true;
|
||||
nmask->eth_dst = qemu_mac_strdup_printf(mask->eth.dst.a);
|
||||
}
|
||||
|
||||
if (key->eth.type) {
|
||||
|
||||
nkey->has_eth_type = true;
|
||||
nkey->eth_type = ntohs(key->eth.type);
|
||||
|
||||
switch (ntohs(key->eth.type)) {
|
||||
case 0x0800:
|
||||
case 0x86dd:
|
||||
if (key->ip.proto || mask->ip.proto) {
|
||||
nkey->has_ip_proto = true;
|
||||
nkey->ip_proto = key->ip.proto;
|
||||
}
|
||||
if (nkey->has_ip_proto && mask->ip.proto != 0xff) {
|
||||
nmask->has_ip_proto = true;
|
||||
nmask->ip_proto = mask->ip.proto;
|
||||
}
|
||||
if (key->ip.tos || mask->ip.tos) {
|
||||
nkey->has_ip_tos = true;
|
||||
nkey->ip_tos = key->ip.tos;
|
||||
}
|
||||
if (nkey->has_ip_tos && mask->ip.tos != 0xff) {
|
||||
nmask->has_ip_tos = true;
|
||||
nmask->ip_tos = mask->ip.tos;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
switch (ntohs(key->eth.type)) {
|
||||
case 0x0800:
|
||||
if (key->ipv4.addr.dst || mask->ipv4.addr.dst) {
|
||||
char *dst = inet_ntoa(*(struct in_addr *)&key->ipv4.addr.dst);
|
||||
int dst_len = of_dpa_mask2prefix(mask->ipv4.addr.dst);
|
||||
nkey->has_ip_dst = true;
|
||||
nkey->ip_dst = g_strdup_printf("%s/%d", dst, dst_len);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (flow->action.goto_tbl) {
|
||||
naction->has_goto_tbl = true;
|
||||
naction->goto_tbl = flow->action.goto_tbl;
|
||||
}
|
||||
|
||||
if (flow->action.write.group_id) {
|
||||
naction->has_group_id = true;
|
||||
naction->group_id = flow->action.write.group_id;
|
||||
}
|
||||
|
||||
if (flow->action.apply.new_vlan_id) {
|
||||
naction->has_new_vlan_id = true;
|
||||
naction->new_vlan_id = flow->action.apply.new_vlan_id;
|
||||
}
|
||||
|
||||
new->next = flow_context->list;
|
||||
flow_context->list = new;
|
||||
}
|
||||
|
||||
RockerOfDpaFlowList *qmp_query_rocker_of_dpa_flows(const char *name,
|
||||
bool has_tbl_id,
|
||||
uint32_t tbl_id,
|
||||
Error **errp)
|
||||
{
|
||||
struct rocker *r;
|
||||
struct world *w;
|
||||
struct of_dpa *of_dpa;
|
||||
struct of_dpa_flow_fill_context fill_context = {
|
||||
.list = NULL,
|
||||
.tbl_id = tbl_id,
|
||||
};
|
||||
|
||||
r = rocker_find(name);
|
||||
if (!r) {
|
||||
error_set(errp, ERROR_CLASS_GENERIC_ERROR,
|
||||
"rocker %s not found", name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
w = rocker_get_world(r, ROCKER_WORLD_TYPE_OF_DPA);
|
||||
if (!w) {
|
||||
error_set(errp, ERROR_CLASS_GENERIC_ERROR,
|
||||
"rocker %s doesn't have OF-DPA world", name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
of_dpa = world_private(w);
|
||||
|
||||
g_hash_table_foreach(of_dpa->flow_tbl, of_dpa_flow_fill, &fill_context);
|
||||
|
||||
return fill_context.list;
|
||||
}
|
||||
|
||||
struct of_dpa_group_fill_context {
|
||||
RockerOfDpaGroupList *list;
|
||||
uint8_t type;
|
||||
};
|
||||
|
||||
static void of_dpa_group_fill(void *key, void *value, void *user_data)
|
||||
{
|
||||
struct of_dpa_group *group = value;
|
||||
struct of_dpa_group_fill_context *flow_context = user_data;
|
||||
RockerOfDpaGroupList *new;
|
||||
RockerOfDpaGroup *ngroup;
|
||||
struct uint32List *id;
|
||||
int i;
|
||||
|
||||
if (flow_context->type != 9 &&
|
||||
flow_context->type != ROCKER_GROUP_TYPE_GET(group->id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
new = g_malloc0(sizeof(*new));
|
||||
ngroup = new->value = g_malloc0(sizeof(*ngroup));
|
||||
|
||||
ngroup->id = group->id;
|
||||
|
||||
ngroup->type = ROCKER_GROUP_TYPE_GET(group->id);
|
||||
|
||||
switch (ngroup->type) {
|
||||
case ROCKER_OF_DPA_GROUP_TYPE_L2_INTERFACE:
|
||||
ngroup->has_vlan_id = true;
|
||||
ngroup->vlan_id = ROCKER_GROUP_VLAN_GET(group->id);
|
||||
ngroup->has_pport = true;
|
||||
ngroup->pport = ROCKER_GROUP_PORT_GET(group->id);
|
||||
ngroup->has_out_pport = true;
|
||||
ngroup->out_pport = group->l2_interface.out_pport;
|
||||
ngroup->has_pop_vlan = true;
|
||||
ngroup->pop_vlan = group->l2_interface.pop_vlan;
|
||||
break;
|
||||
case ROCKER_OF_DPA_GROUP_TYPE_L2_REWRITE:
|
||||
ngroup->has_index = true;
|
||||
ngroup->index = ROCKER_GROUP_INDEX_LONG_GET(group->id);
|
||||
ngroup->has_group_id = true;
|
||||
ngroup->group_id = group->l2_rewrite.group_id;
|
||||
if (group->l2_rewrite.vlan_id) {
|
||||
ngroup->has_set_vlan_id = true;
|
||||
ngroup->set_vlan_id = ntohs(group->l2_rewrite.vlan_id);
|
||||
}
|
||||
break;
|
||||
if (memcmp(group->l2_rewrite.src_mac.a, zero_mac.a, ETH_ALEN)) {
|
||||
ngroup->has_set_eth_src = true;
|
||||
ngroup->set_eth_src =
|
||||
qemu_mac_strdup_printf(group->l2_rewrite.src_mac.a);
|
||||
}
|
||||
if (memcmp(group->l2_rewrite.dst_mac.a, zero_mac.a, ETH_ALEN)) {
|
||||
ngroup->has_set_eth_dst = true;
|
||||
ngroup->set_eth_dst =
|
||||
qemu_mac_strdup_printf(group->l2_rewrite.dst_mac.a);
|
||||
}
|
||||
case ROCKER_OF_DPA_GROUP_TYPE_L2_FLOOD:
|
||||
case ROCKER_OF_DPA_GROUP_TYPE_L2_MCAST:
|
||||
ngroup->has_vlan_id = true;
|
||||
ngroup->vlan_id = ROCKER_GROUP_VLAN_GET(group->id);
|
||||
ngroup->has_index = true;
|
||||
ngroup->index = ROCKER_GROUP_INDEX_GET(group->id);
|
||||
for (i = 0; i < group->l2_flood.group_count; i++) {
|
||||
ngroup->has_group_ids = true;
|
||||
id = g_malloc0(sizeof(*id));
|
||||
id->value = group->l2_flood.group_ids[i];
|
||||
id->next = ngroup->group_ids;
|
||||
ngroup->group_ids = id;
|
||||
}
|
||||
break;
|
||||
case ROCKER_OF_DPA_GROUP_TYPE_L3_UCAST:
|
||||
ngroup->has_index = true;
|
||||
ngroup->index = ROCKER_GROUP_INDEX_LONG_GET(group->id);
|
||||
ngroup->has_group_id = true;
|
||||
ngroup->group_id = group->l3_unicast.group_id;
|
||||
if (group->l3_unicast.vlan_id) {
|
||||
ngroup->has_set_vlan_id = true;
|
||||
ngroup->set_vlan_id = ntohs(group->l3_unicast.vlan_id);
|
||||
}
|
||||
if (memcmp(group->l3_unicast.src_mac.a, zero_mac.a, ETH_ALEN)) {
|
||||
ngroup->has_set_eth_src = true;
|
||||
ngroup->set_eth_src =
|
||||
qemu_mac_strdup_printf(group->l3_unicast.src_mac.a);
|
||||
}
|
||||
if (memcmp(group->l3_unicast.dst_mac.a, zero_mac.a, ETH_ALEN)) {
|
||||
ngroup->has_set_eth_dst = true;
|
||||
ngroup->set_eth_dst =
|
||||
qemu_mac_strdup_printf(group->l3_unicast.dst_mac.a);
|
||||
}
|
||||
if (group->l3_unicast.ttl_check) {
|
||||
ngroup->has_ttl_check = true;
|
||||
ngroup->ttl_check = group->l3_unicast.ttl_check;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
new->next = flow_context->list;
|
||||
flow_context->list = new;
|
||||
}
|
||||
|
||||
RockerOfDpaGroupList *qmp_query_rocker_of_dpa_groups(const char *name,
|
||||
bool has_type,
|
||||
uint8_t type,
|
||||
Error **errp)
|
||||
{
|
||||
struct rocker *r;
|
||||
struct world *w;
|
||||
struct of_dpa *of_dpa;
|
||||
struct of_dpa_group_fill_context fill_context = {
|
||||
.list = NULL,
|
||||
.type = type,
|
||||
};
|
||||
|
||||
r = rocker_find(name);
|
||||
if (!r) {
|
||||
error_set(errp, ERROR_CLASS_GENERIC_ERROR,
|
||||
"rocker %s not found", name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
w = rocker_get_world(r, ROCKER_WORLD_TYPE_OF_DPA);
|
||||
if (!w) {
|
||||
error_set(errp, ERROR_CLASS_GENERIC_ERROR,
|
||||
"rocker %s doesn't have OF-DPA world", name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
of_dpa = world_private(w);
|
||||
|
||||
g_hash_table_foreach(of_dpa->group_tbl, of_dpa_group_fill, &fill_context);
|
||||
|
||||
return fill_context.list;
|
||||
}
|
||||
|
||||
static WorldOps of_dpa_ops = {
|
||||
.init = of_dpa_init,
|
||||
.uninit = of_dpa_uninit,
|
||||
|
28
monitor.c
28
monitor.c
@ -2862,6 +2862,34 @@ static mon_cmd_t info_cmds[] = {
|
||||
.help = "show memory devices",
|
||||
.mhandler.cmd = hmp_info_memory_devices,
|
||||
},
|
||||
{
|
||||
.name = "rocker",
|
||||
.args_type = "name:s",
|
||||
.params = "name",
|
||||
.help = "Show rocker switch",
|
||||
.mhandler.cmd = hmp_rocker,
|
||||
},
|
||||
{
|
||||
.name = "rocker-ports",
|
||||
.args_type = "name:s",
|
||||
.params = "name",
|
||||
.help = "Show rocker ports",
|
||||
.mhandler.cmd = hmp_rocker_ports,
|
||||
},
|
||||
{
|
||||
.name = "rocker-of-dpa-flows",
|
||||
.args_type = "name:s,tbl_id:i?",
|
||||
.params = "name [tbl_id]",
|
||||
.help = "Show rocker OF-DPA flow tables",
|
||||
.mhandler.cmd = hmp_rocker_of_dpa_flows,
|
||||
},
|
||||
{
|
||||
.name = "rocker-of-dpa-groups",
|
||||
.args_type = "name:s,type:i?",
|
||||
.params = "name [type]",
|
||||
.help = "Show rocker OF-DPA groups",
|
||||
.mhandler.cmd = hmp_rocker_of_dpa_groups,
|
||||
},
|
||||
{
|
||||
.name = NULL,
|
||||
},
|
||||
|
@ -3788,3 +3788,6 @@
|
||||
# Since: 2.1
|
||||
##
|
||||
{ 'command': 'rtc-reset-reinjection' }
|
||||
|
||||
# Rocker ethernet network switch
|
||||
{ 'include': 'qapi/rocker.json' }
|
||||
|
286
qapi/rocker.json
Normal file
286
qapi/rocker.json
Normal file
@ -0,0 +1,286 @@
|
||||
##
|
||||
# @Rocker:
|
||||
#
|
||||
# Rocker switch information.
|
||||
#
|
||||
# @name: switch name
|
||||
#
|
||||
# @id: switch ID
|
||||
#
|
||||
# @ports: number of front-panel ports
|
||||
#
|
||||
# Since: 2.4
|
||||
##
|
||||
{ 'struct': 'RockerSwitch',
|
||||
'data': { 'name': 'str', 'id': 'uint64', 'ports': 'uint32' } }
|
||||
|
||||
##
|
||||
# @query-rocker:
|
||||
#
|
||||
# Return rocker switch information.
|
||||
#
|
||||
# Returns: @Rocker information
|
||||
#
|
||||
# Since: 2.4
|
||||
##
|
||||
{ 'command': 'query-rocker',
|
||||
'data': { 'name': 'str' },
|
||||
'returns': 'RockerSwitch' }
|
||||
|
||||
##
|
||||
# @RockerPortDuplex:
|
||||
#
|
||||
# An eumeration of port duplex states.
|
||||
#
|
||||
# @half: half duplex
|
||||
#
|
||||
# @full: full duplex
|
||||
#
|
||||
# Since: 2.4
|
||||
##
|
||||
{ 'enum': 'RockerPortDuplex', 'data': [ 'half', 'full' ] }
|
||||
|
||||
##
|
||||
# @RockerPortAutoneg:
|
||||
#
|
||||
# An eumeration of port autoneg states.
|
||||
#
|
||||
# @off: autoneg is off
|
||||
#
|
||||
# @on: autoneg is on
|
||||
#
|
||||
# Since: 2.4
|
||||
##
|
||||
{ 'enum': 'RockerPortAutoneg', 'data': [ 'off', 'on' ] }
|
||||
|
||||
##
|
||||
# @RockerPort:
|
||||
#
|
||||
# Rocker switch port information.
|
||||
#
|
||||
# @name: port name
|
||||
#
|
||||
# @enabled: port is enabled for I/O
|
||||
#
|
||||
# @link-up: physical link is UP on port
|
||||
#
|
||||
# @speed: port link speed in Mbps
|
||||
#
|
||||
# @duplex: port link duplex
|
||||
#
|
||||
# @autoneg: port link autoneg
|
||||
#
|
||||
# Since: 2.4
|
||||
##
|
||||
{ 'struct': 'RockerPort',
|
||||
'data': { 'name': 'str', 'enabled': 'bool', 'link-up': 'bool',
|
||||
'speed': 'uint32', 'duplex': 'RockerPortDuplex',
|
||||
'autoneg': 'RockerPortAutoneg' } }
|
||||
|
||||
##
|
||||
# @query-rocker-ports:
|
||||
#
|
||||
# Return rocker switch information.
|
||||
#
|
||||
# Returns: @Rocker information
|
||||
#
|
||||
# Since: 2.4
|
||||
##
|
||||
{ 'command': 'query-rocker-ports',
|
||||
'data': { 'name': 'str' },
|
||||
'returns': ['RockerPort'] }
|
||||
|
||||
##
|
||||
# @RockerOfDpaFlowKey:
|
||||
#
|
||||
# Rocker switch OF-DPA flow key
|
||||
#
|
||||
# @priority: key priority, 0 being lowest priority
|
||||
#
|
||||
# @tbl-id: flow table ID
|
||||
#
|
||||
# @in-pport: #optional physical input port
|
||||
#
|
||||
# @tunnel-id: #optional tunnel ID
|
||||
#
|
||||
# @vlan-id: #optional VLAN ID
|
||||
#
|
||||
# @eth-type: #optional Ethernet header type
|
||||
#
|
||||
# @eth-src: #optional Ethernet header source MAC address
|
||||
#
|
||||
# @eth-dst: #optional Ethernet header destination MAC address
|
||||
#
|
||||
# @ip-proto: #optional IP Header protocol field
|
||||
#
|
||||
# @ip-tos: #optional IP header TOS field
|
||||
#
|
||||
# @ip-dst: #optional IP header destination address
|
||||
#
|
||||
# Note: fields are marked #optional to indicate that they may or may not
|
||||
# appear in the flow key depending if they're relevant to the flow key.
|
||||
#
|
||||
# Since: 2.4
|
||||
##
|
||||
{ 'struct': 'RockerOfDpaFlowKey',
|
||||
'data' : { 'priority': 'uint32', 'tbl-id': 'uint32', '*in-pport': 'uint32',
|
||||
'*tunnel-id': 'uint32', '*vlan-id': 'uint16',
|
||||
'*eth-type': 'uint16', '*eth-src': 'str', '*eth-dst': 'str',
|
||||
'*ip-proto': 'uint8', '*ip-tos': 'uint8', '*ip-dst': 'str' } }
|
||||
|
||||
##
|
||||
# @RockerOfDpaFlowMask:
|
||||
#
|
||||
# Rocker switch OF-DPA flow mask
|
||||
#
|
||||
# @in-pport: #optional physical input port
|
||||
#
|
||||
# @tunnel-id: #optional tunnel ID
|
||||
#
|
||||
# @vlan-id: #optional VLAN ID
|
||||
#
|
||||
# @eth-src: #optional Ethernet header source MAC address
|
||||
#
|
||||
# @eth-dst: #optional Ethernet header destination MAC address
|
||||
#
|
||||
# @ip-proto: #optional IP Header protocol field
|
||||
#
|
||||
# @ip-tos: #optional IP header TOS field
|
||||
#
|
||||
# Note: fields are marked #optional to indicate that they may or may not
|
||||
# appear in the flow mask depending if they're relevant to the flow mask.
|
||||
#
|
||||
# Since: 2.4
|
||||
##
|
||||
{ 'struct': 'RockerOfDpaFlowMask',
|
||||
'data' : { '*in-pport': 'uint32', '*tunnel-id': 'uint32',
|
||||
'*vlan-id': 'uint16', '*eth-src': 'str', '*eth-dst': 'str',
|
||||
'*ip-proto': 'uint8', '*ip-tos': 'uint8' } }
|
||||
|
||||
##
|
||||
# @RockerOfDpaFlowAction:
|
||||
#
|
||||
# Rocker switch OF-DPA flow action
|
||||
#
|
||||
# @goto-tbl: #optional next table ID
|
||||
#
|
||||
# @group-id: #optional group ID
|
||||
#
|
||||
# @tunnel-lport: #optional tunnel logical port ID
|
||||
#
|
||||
# @vlan-id: #optional VLAN ID
|
||||
#
|
||||
# @new-vlan-id: #optional new VLAN ID
|
||||
#
|
||||
# @out-pport: #optional physical output port
|
||||
#
|
||||
# Note: fields are marked #optional to indicate that they may or may not
|
||||
# appear in the flow action depending if they're relevant to the flow action.
|
||||
#
|
||||
# Since: 2.4
|
||||
##
|
||||
{ 'struct': 'RockerOfDpaFlowAction',
|
||||
'data' : { '*goto-tbl': 'uint32', '*group-id': 'uint32',
|
||||
'*tunnel-lport': 'uint32', '*vlan-id': 'uint16',
|
||||
'*new-vlan-id': 'uint16', '*out-pport': 'uint32' } }
|
||||
|
||||
##
|
||||
# @RockerOfDpaFlow:
|
||||
#
|
||||
# Rocker switch OF-DPA flow
|
||||
#
|
||||
# @cookie: flow unique cookie ID
|
||||
#
|
||||
# @hits: count of matches (hits) on flow
|
||||
#
|
||||
# @key: flow key
|
||||
#
|
||||
# @mask: flow mask
|
||||
#
|
||||
# @action: flow action
|
||||
#
|
||||
# Since: 2.4
|
||||
##
|
||||
{ 'struct': 'RockerOfDpaFlow',
|
||||
'data': { 'cookie': 'uint64', 'hits': 'uint64', 'key': 'RockerOfDpaFlowKey',
|
||||
'mask': 'RockerOfDpaFlowMask', 'action': 'RockerOfDpaFlowAction' } }
|
||||
|
||||
##
|
||||
# @query-rocker-of-dpa-flows:
|
||||
#
|
||||
# Return rocker OF-DPA flow information.
|
||||
#
|
||||
# @name: switch name
|
||||
#
|
||||
# @tbl-id: #optional flow table ID. If tbl-id is not specified, returns
|
||||
# flow information for all tables.
|
||||
#
|
||||
# Returns: @Rocker OF-DPA flow information
|
||||
#
|
||||
# Since: 2.4
|
||||
##
|
||||
{ 'command': 'query-rocker-of-dpa-flows',
|
||||
'data': { 'name': 'str', '*tbl-id': 'uint32' },
|
||||
'returns': ['RockerOfDpaFlow'] }
|
||||
|
||||
##
|
||||
# @RockerOfDpaGroup:
|
||||
#
|
||||
# Rocker switch OF-DPA group
|
||||
#
|
||||
# @id: group unique ID
|
||||
#
|
||||
# @type: group type
|
||||
#
|
||||
# @vlan-id: #optional VLAN ID
|
||||
#
|
||||
# @pport: #optional physical port number
|
||||
#
|
||||
# @index: #optional group index, unique with group type
|
||||
#
|
||||
# @out-pport: #optional output physical port number
|
||||
#
|
||||
# @group-id: #optional next group ID
|
||||
#
|
||||
# @set-vlan-id: #optional VLAN ID to set
|
||||
#
|
||||
# @pop-vlan: #optional pop VLAN headr from packet
|
||||
#
|
||||
# @group-ids: #optional list of next group IDs
|
||||
#
|
||||
# @set-eth-src: #optional set source MAC address in Ethernet header
|
||||
#
|
||||
# @set-eth-dst: #optional set destination MAC address in Ethernet header
|
||||
#
|
||||
# @ttl-check: #optional perform TTL check
|
||||
#
|
||||
# Note: fields are marked #optional to indicate that they may or may not
|
||||
# appear in the group depending if they're relevant to the group type.
|
||||
#
|
||||
# Since: 2.4
|
||||
##
|
||||
{ 'struct': 'RockerOfDpaGroup',
|
||||
'data': { 'id': 'uint32', 'type': 'uint8', '*vlan-id': 'uint16',
|
||||
'*pport': 'uint32', '*index': 'uint32', '*out-pport': 'uint32',
|
||||
'*group-id': 'uint32', '*set-vlan-id': 'uint16',
|
||||
'*pop-vlan': 'uint8', '*group-ids': ['uint32'],
|
||||
'*set-eth-src': 'str', '*set-eth-dst': 'str',
|
||||
'*ttl-check': 'uint8' } }
|
||||
|
||||
##
|
||||
# @query-rocker-of-dpa-groups:
|
||||
#
|
||||
# Return rocker OF-DPA group information.
|
||||
#
|
||||
# @name: switch name
|
||||
#
|
||||
# @type: #optional group type. If type is not specified, returns
|
||||
# group information for all group types.
|
||||
#
|
||||
# Returns: @Rocker OF-DPA group information
|
||||
#
|
||||
# Since: 2.4
|
||||
##
|
||||
{ 'command': 'query-rocker-of-dpa-groups',
|
||||
'data': { 'name': 'str', '*type': 'uint8' },
|
||||
'returns': ['RockerOfDpaGroup'] }
|
103
qmp-commands.hx
103
qmp-commands.hx
@ -4165,3 +4165,106 @@ Example:
|
||||
<- { "return": {} }
|
||||
|
||||
EQMP
|
||||
|
||||
{
|
||||
.name = "query-rocker",
|
||||
.args_type = "name:s",
|
||||
.mhandler.cmd_new = qmp_marshal_input_query_rocker,
|
||||
},
|
||||
|
||||
SQMP
|
||||
Show rocker switch
|
||||
------------------
|
||||
|
||||
Arguments:
|
||||
|
||||
- "name": switch name
|
||||
|
||||
Example:
|
||||
|
||||
-> { "execute": "query-rocker", "arguments": { "name": "sw1" } }
|
||||
<- { "return": {"name": "sw1", "ports": 2, "id": 1327446905938}}
|
||||
|
||||
EQMP
|
||||
|
||||
{
|
||||
.name = "query-rocker-ports",
|
||||
.args_type = "name:s",
|
||||
.mhandler.cmd_new = qmp_marshal_input_query_rocker_ports,
|
||||
},
|
||||
|
||||
SQMP
|
||||
Show rocker switch ports
|
||||
------------------------
|
||||
|
||||
Arguments:
|
||||
|
||||
- "name": switch name
|
||||
|
||||
Example:
|
||||
|
||||
-> { "execute": "query-rocker-ports", "arguments": { "name": "sw1" } }
|
||||
<- { "return": [ {"duplex": "full", "enabled": true, "name": "sw1.1",
|
||||
"autoneg": "off", "link-up": true, "speed": 10000},
|
||||
{"duplex": "full", "enabled": true, "name": "sw1.2",
|
||||
"autoneg": "off", "link-up": true, "speed": 10000}
|
||||
]}
|
||||
|
||||
EQMP
|
||||
|
||||
{
|
||||
.name = "query-rocker-of-dpa-flows",
|
||||
.args_type = "name:s,tbl-id:i?",
|
||||
.mhandler.cmd_new = qmp_marshal_input_query_rocker_of_dpa_flows,
|
||||
},
|
||||
|
||||
SQMP
|
||||
Show rocker switch OF-DPA flow tables
|
||||
-------------------------------------
|
||||
|
||||
Arguments:
|
||||
|
||||
- "name": switch name
|
||||
- "tbl-id": (optional) flow table ID
|
||||
|
||||
Example:
|
||||
|
||||
-> { "execute": "query-rocker-of-dpa-flows", "arguments": { "name": "sw1" } }
|
||||
<- { "return": [ {"key": {"in-pport": 0, "priority": 1, "tbl-id": 0},
|
||||
"hits": 138,
|
||||
"cookie": 0,
|
||||
"action": {"goto-tbl": 10},
|
||||
"mask": {"in-pport": 4294901760}
|
||||
},
|
||||
{...more...},
|
||||
]}
|
||||
|
||||
EQMP
|
||||
|
||||
{
|
||||
.name = "query-rocker-of-dpa-groups",
|
||||
.args_type = "name:s,type:i?",
|
||||
.mhandler.cmd_new = qmp_marshal_input_query_rocker_of_dpa_groups,
|
||||
},
|
||||
|
||||
SQMP
|
||||
Show rocker OF-DPA group tables
|
||||
-------------------------------
|
||||
|
||||
Arguments:
|
||||
|
||||
- "name": switch name
|
||||
- "type": (optional) group type
|
||||
|
||||
Example:
|
||||
|
||||
-> { "execute": "query-rocker-of-dpa-groups", "arguments": { "name": "sw1" } }
|
||||
<- { "return": [ {"type": 0, "out-pport": 2, "pport": 2, "vlan-id": 3841,
|
||||
"pop-vlan": 1, "id": 251723778},
|
||||
{"type": 0, "out-pport": 0, "pport": 0, "vlan-id": 3841,
|
||||
"pop-vlan": 1, "id": 251723776},
|
||||
{"type": 0, "out-pport": 1, "pport": 1, "vlan-id": 3840,
|
||||
"pop-vlan": 1, "id": 251658241},
|
||||
{"type": 0, "out-pport": 0, "pport": 0, "vlan-id": 3840,
|
||||
"pop-vlan": 1, "id": 251658240}
|
||||
]}
|
||||
|
Loading…
Reference in New Issue
Block a user