* [Qemu-devel] [PATCH v3 0/4] rocker device updates
@ 2015-05-29 14:01 sfeldma
2015-05-29 14:01 ` [Qemu-devel] [PATCH v3 1/4] rocker: Add support for phys name sfeldma
` (4 more replies)
0 siblings, 5 replies; 9+ messages in thread
From: sfeldma @ 2015-05-29 14:01 UTC (permalink / raw)
To: qemu-devel; +Cc: stefanha, jiri, dsahern
From: Scott Feldman <sfeldma@gmail.com>
v3:
Address review comments from Stefan Hajnoczi:
- Add missing hw/net/rocker/qmp-norocker.c file.
- Add missing curly brackets to a for loop
v2:
Address some review comments by Stefan Hajnoczi: see individual patches for
v1->v2 changes.
v1:
Some rocker device updates we've been holding onto waiting for base rocker
device to be pulled into 2.4. David added support for the device to return the
physical port name, which in turn can be used by the OS to name the interface.
I added a small change the bringe link up/down when port is enabled/disabled.
The big addition is adding qmp/hmp support to rocker. This was included in the
original rocker device patch set, but pulled as there where last-minute issues
with building on non-PCI targets. These issues have been addressed by stubbing
out qmp/hmp support when rocker device is built for non-PCI targets.
David Ahern (1):
rocker: Add support for phys name
Scott Feldman (3):
rocker: update tests using hw-derived interface names
rocker: bring link up/down on PHY enable/disable
qmp/hmp: add rocker device support
docs/specs/rocker.txt | 1 +
hmp-commands.hx | 24 ++++
hmp.c | 303 +++++++++++++++++++++++++++++++++++++++
hmp.h | 4 +
hw/net/Makefile.objs | 1 +
hw/net/rocker/qmp-norocker.c | 50 +++++++
hw/net/rocker/rocker.c | 68 ++++++++-
hw/net/rocker/rocker_fp.c | 29 +++-
hw/net/rocker/rocker_fp.h | 2 +
hw/net/rocker/rocker_hw.h | 1 +
hw/net/rocker/rocker_of_dpa.c | 312 +++++++++++++++++++++++++++++++++++++++++
monitor.c | 28 ++++
qapi-schema.json | 3 +
qapi/rocker.json | 286 +++++++++++++++++++++++++++++++++++++
qmp-commands.hx | 97 +++++++++++++
tests/rocker/bridge | 25 ++--
tests/rocker/bridge-stp | 25 ++--
tests/rocker/bridge-vlan | 37 +++--
tests/rocker/bridge-vlan-stp | 37 +++--
tests/rocker/port | 8 +-
20 files changed, 1263 insertions(+), 78 deletions(-)
create mode 100644 hw/net/rocker/qmp-norocker.c
create mode 100644 qapi/rocker.json
--
1.7.10.4
^ permalink raw reply [flat|nested] 9+ messages in thread
* [Qemu-devel] [PATCH v3 1/4] rocker: Add support for phys name
2015-05-29 14:01 [Qemu-devel] [PATCH v3 0/4] rocker device updates sfeldma
@ 2015-05-29 14:01 ` sfeldma
2015-06-02 16:27 ` Eric Blake
2015-05-29 14:01 ` [Qemu-devel] [PATCH v3 2/4] rocker: update tests using hw-derived interface names sfeldma
` (3 subsequent siblings)
4 siblings, 1 reply; 9+ messages in thread
From: sfeldma @ 2015-05-29 14:01 UTC (permalink / raw)
To: qemu-devel; +Cc: stefanha, jiri, dsahern
From: David Ahern <dsahern@gmail.com>
v2:
Review comment from Stefan Hajnoczi:
- use private ROCKER_IFNAMSIZ = 16 to avoid breaking Windows build
as Windows does not include <net/if.h>
v1:
Add ROCKER_TLV_CMD_PORT_SETTINGS_PHYS_NAME to port settings. This attribute
exports the port name to the guest OS allowing it to name interfaces with
sensible defaults.
Mostly done by Scott for phys_id support; adapted to phys_name by David.
Signed-off-by: Scott Feldman <sfeldma@gmail.com>
Signed-off-by: David Ahern <dsahern@gmail.com>
---
docs/specs/rocker.txt | 1 +
hw/net/rocker/rocker.c | 23 ++++++++++++++++++++++-
hw/net/rocker/rocker_fp.c | 7 ++++++-
hw/net/rocker/rocker_fp.h | 1 +
hw/net/rocker/rocker_hw.h | 1 +
5 files changed, 31 insertions(+), 2 deletions(-)
diff --git a/docs/specs/rocker.txt b/docs/specs/rocker.txt
index 1e7e1e1..0af5c61 100644
--- a/docs/specs/rocker.txt
+++ b/docs/specs/rocker.txt
@@ -420,6 +420,7 @@ Other properties for front-panel ports are available via DMA CMD descriptors:
LEARNING 1 MAC address learning on port
1 = enabled
0 = disabled
+ PHYS_NAME <var> Physical port name (string)
Set PORT_SETTINGS descriptor:
diff --git a/hw/net/rocker/rocker.c b/hw/net/rocker/rocker.c
index 55b6c46..e74c027 100644
--- a/hw/net/rocker/rocker.c
+++ b/hw/net/rocker/rocker.c
@@ -238,6 +238,7 @@ static int cmd_get_port_settings(Rocker *r,
uint8_t duplex;
uint8_t autoneg;
uint8_t learning;
+ char *phys_name;
MACAddr macaddr;
enum rocker_world_type mode;
size_t tlv_size;
@@ -265,6 +266,7 @@ static int cmd_get_port_settings(Rocker *r,
fp_port_get_macaddr(fp_port, &macaddr);
mode = world_type(fp_port_get_world(fp_port));
learning = fp_port_get_learning(fp_port);
+ phys_name = fp_port_get_name(fp_port);
tlv_size = rocker_tlv_total_size(0) + /* nest */
rocker_tlv_total_size(sizeof(uint32_t)) + /* pport */
@@ -273,7 +275,8 @@ static int cmd_get_port_settings(Rocker *r,
rocker_tlv_total_size(sizeof(uint8_t)) + /* autoneg */
rocker_tlv_total_size(sizeof(macaddr.a)) + /* macaddr */
rocker_tlv_total_size(sizeof(uint8_t)) + /* mode */
- rocker_tlv_total_size(sizeof(uint8_t)); /* learning */
+ rocker_tlv_total_size(sizeof(uint8_t)) + /* learning */
+ rocker_tlv_total_size(strlen(phys_name));
if (tlv_size > desc_buf_size(info)) {
return -ROCKER_EMSGSIZE;
@@ -290,6 +293,8 @@ static int cmd_get_port_settings(Rocker *r,
rocker_tlv_put_u8(buf, &pos, ROCKER_TLV_CMD_PORT_SETTINGS_MODE, mode);
rocker_tlv_put_u8(buf, &pos, ROCKER_TLV_CMD_PORT_SETTINGS_LEARNING,
learning);
+ rocker_tlv_put(buf, &pos, ROCKER_TLV_CMD_PORT_SETTINGS_PHYS_NAME,
+ strlen(phys_name), phys_name);
rocker_tlv_nest_end(buf, &pos, nest);
return desc_set_buf(info, tlv_size);
@@ -1277,6 +1282,22 @@ static int pci_rocker_init(PCIDevice *dev)
goto err_duplicate;
}
+ /* Rocker name is passed in port name requests to OS with the intention
+ * that the name is used in interface names. Limit the length of the
+ * rocker name to avoid naming problems in the OS. Also, adding the
+ * port number as p# and unganged breakout b#, where # is at most 2
+ * digits, so leave room for it too (-1 for string terminator, -3 for
+ * p# and -3 for b#)
+ */
+#define ROCKER_IFNAMSIZ 16
+#define MAX_ROCKER_NAME_LEN (ROCKER_IFNAMSIZ - 1 - 3 - 3)
+ if (strlen(r->name) > MAX_ROCKER_NAME_LEN) {
+ fprintf(stderr,
+ "rocker: name too long; please shorten to at most %d chars\n",
+ MAX_ROCKER_NAME_LEN);
+ return -EINVAL;
+ }
+
if (memcmp(&r->fp_start_macaddr, &zero, sizeof(zero)) == 0) {
memcpy(&r->fp_start_macaddr, &dflt, sizeof(dflt));
r->fp_start_macaddr.a[4] += (sw_index++);
diff --git a/hw/net/rocker/rocker_fp.c b/hw/net/rocker/rocker_fp.c
index 2f1e3b3..393e9e7 100644
--- a/hw/net/rocker/rocker_fp.c
+++ b/hw/net/rocker/rocker_fp.c
@@ -41,6 +41,11 @@ struct fp_port {
NICConf conf;
};
+char *fp_port_get_name(FpPort *port)
+{
+ return port->name;
+}
+
bool fp_port_get_link_up(FpPort *port)
{
return !qemu_get_queue(port->nic)->link_down;
@@ -201,7 +206,7 @@ FpPort *fp_port_alloc(Rocker *r, char *sw_name,
/* front-panel switch port names are 1-based */
- port->name = g_strdup_printf("%s.%d", sw_name, port->pport);
+ port->name = g_strdup_printf("%sp%d", sw_name, port->pport);
memcpy(port->conf.macaddr.a, start_mac, sizeof(port->conf.macaddr.a));
port->conf.macaddr.a[5] += index;
diff --git a/hw/net/rocker/rocker_fp.h b/hw/net/rocker/rocker_fp.h
index a5f28f1..92a6861 100644
--- a/hw/net/rocker/rocker_fp.h
+++ b/hw/net/rocker/rocker_fp.h
@@ -26,6 +26,7 @@ typedef struct fp_port FpPort;
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_macaddr(FpPort *port, MACAddr *macaddr);
void fp_port_set_macaddr(FpPort *port, MACAddr *macaddr);
diff --git a/hw/net/rocker/rocker_hw.h b/hw/net/rocker/rocker_hw.h
index c9c85a7..fe639ba 100644
--- a/hw/net/rocker/rocker_hw.h
+++ b/hw/net/rocker/rocker_hw.h
@@ -179,6 +179,7 @@ enum {
ROCKER_TLV_CMD_PORT_SETTINGS_MACADDR, /* binary */
ROCKER_TLV_CMD_PORT_SETTINGS_MODE, /* u8 */
ROCKER_TLV_CMD_PORT_SETTINGS_LEARNING, /* u8 */
+ ROCKER_TLV_CMD_PORT_SETTINGS_PHYS_NAME, /* binary */
__ROCKER_TLV_CMD_PORT_SETTINGS_MAX,
ROCKER_TLV_CMD_PORT_SETTINGS_MAX = __ROCKER_TLV_CMD_PORT_SETTINGS_MAX - 1,
--
1.7.10.4
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [Qemu-devel] [PATCH v3 2/4] rocker: update tests using hw-derived interface names
2015-05-29 14:01 [Qemu-devel] [PATCH v3 0/4] rocker device updates sfeldma
2015-05-29 14:01 ` [Qemu-devel] [PATCH v3 1/4] rocker: Add support for phys name sfeldma
@ 2015-05-29 14:01 ` sfeldma
2015-05-29 14:01 ` [Qemu-devel] [PATCH v3 3/4] rocker: bring link up/down on PHY enable/disable sfeldma
` (2 subsequent siblings)
4 siblings, 0 replies; 9+ messages in thread
From: sfeldma @ 2015-05-29 14:01 UTC (permalink / raw)
To: qemu-devel; +Cc: stefanha, jiri, dsahern
From: Scott Feldman <sfeldma@gmail.com>
With previous patch to support phy name attribute for each port, the OS
can name port interfaces using the hw-derived name. So update rocker
tests to use the new hw-derived interface names.
Signed-off-by: Scott Feldman <sfeldma@gmail.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
---
tests/rocker/bridge | 25 ++++++++++---------------
tests/rocker/bridge-stp | 25 ++++++++++---------------
tests/rocker/bridge-vlan | 37 ++++++++++++++++---------------------
tests/rocker/bridge-vlan-stp | 37 ++++++++++++++++---------------------
tests/rocker/port | 8 ++++----
5 files changed, 56 insertions(+), 76 deletions(-)
diff --git a/tests/rocker/bridge b/tests/rocker/bridge
index 7a03f9a..46abc6f 100755
--- a/tests/rocker/bridge
+++ b/tests/rocker/bridge
@@ -9,8 +9,8 @@ while ! simp ssh tut h2 --cmd "ping -c 1 localhost >/dev/null"; do sleep 1; done
# configure a 2-port bridge
simp ssh tut sw1 --cmd "sudo /sbin/ip link add name br0 type bridge"
-simp ssh tut sw1 --cmd "sudo /sbin/ip link set dev swp1 master br0"
-simp ssh tut sw1 --cmd "sudo /sbin/ip link set dev swp2 master br0"
+simp ssh tut sw1 --cmd "sudo /sbin/ip link set dev sw1p1 master br0"
+simp ssh tut sw1 --cmd "sudo /sbin/ip link set dev sw1p2 master br0"
# turn off vlan default_pvid on br0
@@ -18,28 +18,23 @@ simp ssh tut sw1 --cmd "echo 0 | sudo dd of=/sys/class/net/br0/bridge/default_pv
# turn off learning and flooding in SW
-simp ssh tut sw1 --cmd "sudo /sbin/bridge link set dev swp1 learning off"
-simp ssh tut sw1 --cmd "sudo /sbin/bridge link set dev swp2 learning off"
+simp ssh tut sw1 --cmd "sudo /sbin/bridge link set dev sw1p1 learning off"
+simp ssh tut sw1 --cmd "sudo /sbin/bridge link set dev sw1p2 learning off"
-simp ssh tut sw1 --cmd "sudo /sbin/bridge link set dev swp1 flood off"
-simp ssh tut sw1 --cmd "sudo /sbin/bridge link set dev swp2 flood off"
-
-# turn on learning in HW
-
-simp ssh tut sw1 --cmd "sudo /sbin/bridge link set dev swp1 learning on self"
-simp ssh tut sw1 --cmd "sudo /sbin/bridge link set dev swp2 learning on self"
+simp ssh tut sw1 --cmd "sudo /sbin/bridge link set dev sw1p1 flood off"
+simp ssh tut sw1 --cmd "sudo /sbin/bridge link set dev sw1p2 flood off"
# bring up bridge and ports
simp ssh tut sw1 --cmd "sudo ifconfig br0 up"
-simp ssh tut sw1 --cmd "sudo ifconfig swp1 up"
-simp ssh tut sw1 --cmd "sudo ifconfig swp2 up"
+simp ssh tut sw1 --cmd "sudo ifconfig sw1p1 up"
+simp ssh tut sw1 --cmd "sudo ifconfig sw1p2 up"
simp ssh tut sw1 --cmd "sudo ifconfig br0 11.0.0.3/24"
# config IP on hosts
-simp ssh tut h1 --cmd "sudo ifconfig swp1 11.0.0.1/24"
-simp ssh tut h2 --cmd "sudo ifconfig swp1 11.0.0.2/24"
+simp ssh tut h1 --cmd "sudo ifconfig sw1p1 11.0.0.1/24"
+simp ssh tut h2 --cmd "sudo ifconfig sw1p1 11.0.0.2/24"
# test...
diff --git a/tests/rocker/bridge-stp b/tests/rocker/bridge-stp
index 4a111a1..008568a 100755
--- a/tests/rocker/bridge-stp
+++ b/tests/rocker/bridge-stp
@@ -10,8 +10,8 @@ while ! simp ssh tut h2 --cmd "ping -c 1 localhost >/dev/null"; do sleep 1; done
simp ssh tut sw1 --cmd "sudo /sbin/ip link add name br0 type bridge"
simp ssh tut sw1 --cmd "sudo brctl stp br0 on"
-simp ssh tut sw1 --cmd "sudo /sbin/ip link set dev swp1 master br0"
-simp ssh tut sw1 --cmd "sudo /sbin/ip link set dev swp2 master br0"
+simp ssh tut sw1 --cmd "sudo /sbin/ip link set dev sw1p1 master br0"
+simp ssh tut sw1 --cmd "sudo /sbin/ip link set dev sw1p2 master br0"
# turn off vlan default_pvid on br0
@@ -19,27 +19,22 @@ simp ssh tut sw1 --cmd "echo 0 | sudo dd of=/sys/class/net/br0/bridge/default_pv
# turn off learning and flooding in SW
-simp ssh tut sw1 --cmd "sudo /sbin/bridge link set dev swp1 learning off"
-simp ssh tut sw1 --cmd "sudo /sbin/bridge link set dev swp2 learning off"
+simp ssh tut sw1 --cmd "sudo /sbin/bridge link set dev sw1p1 learning off"
+simp ssh tut sw1 --cmd "sudo /sbin/bridge link set dev sw1p2 learning off"
-simp ssh tut sw1 --cmd "sudo /sbin/bridge link set dev swp1 flood off"
-simp ssh tut sw1 --cmd "sudo /sbin/bridge link set dev swp2 flood off"
-
-# turn on learning in HW
-
-simp ssh tut sw1 --cmd "sudo /sbin/bridge link set dev swp1 learning on self"
-simp ssh tut sw1 --cmd "sudo /sbin/bridge link set dev swp2 learning on self"
+simp ssh tut sw1 --cmd "sudo /sbin/bridge link set dev sw1p1 flood off"
+simp ssh tut sw1 --cmd "sudo /sbin/bridge link set dev sw1p2 flood off"
# config IP on hosts
-simp ssh tut h1 --cmd "sudo ifconfig swp1 11.0.0.1/24"
-simp ssh tut h2 --cmd "sudo ifconfig swp1 11.0.0.2/24"
+simp ssh tut h1 --cmd "sudo ifconfig sw1p1 11.0.0.1/24"
+simp ssh tut h2 --cmd "sudo ifconfig sw1p1 11.0.0.2/24"
# bring up bridge and ports
simp ssh tut sw1 --cmd "sudo ifconfig br0 up"
-simp ssh tut sw1 --cmd "sudo ifconfig swp1 up"
-simp ssh tut sw1 --cmd "sudo ifconfig swp2 up"
+simp ssh tut sw1 --cmd "sudo ifconfig sw1p1 up"
+simp ssh tut sw1 --cmd "sudo ifconfig sw1p2 up"
# test...
diff --git a/tests/rocker/bridge-vlan b/tests/rocker/bridge-vlan
index 9fa3431..e32dd0c 100755
--- a/tests/rocker/bridge-vlan
+++ b/tests/rocker/bridge-vlan
@@ -9,8 +9,8 @@ while ! simp ssh tut h2 --cmd "ping -c 1 localhost >/dev/null"; do sleep 1; done
# configure a 2-port bridge
simp ssh tut sw1 --cmd "sudo /sbin/ip link add name br0 type bridge"
-simp ssh tut sw1 --cmd "sudo /sbin/ip link set dev swp1 master br0"
-simp ssh tut sw1 --cmd "sudo /sbin/ip link set dev swp2 master br0"
+simp ssh tut sw1 --cmd "sudo /sbin/ip link set dev sw1p1 master br0"
+simp ssh tut sw1 --cmd "sudo /sbin/ip link set dev sw1p2 master br0"
# turn off vlan default_pvid on br0
# turn on vlan filtering on br0
@@ -20,37 +20,32 @@ simp ssh tut sw1 --cmd "echo 1 | sudo dd of=/sys/class/net/br0/bridge/vlan_filte
# add both ports to VLAN 57
-simp ssh tut sw1 --cmd "sudo /sbin/bridge vlan add vid 57 dev swp1 master"
-simp ssh tut sw1 --cmd "sudo /sbin/bridge vlan add vid 57 dev swp2 master"
+simp ssh tut sw1 --cmd "sudo /sbin/bridge vlan add vid 57 dev sw1p1 master"
+simp ssh tut sw1 --cmd "sudo /sbin/bridge vlan add vid 57 dev sw1p2 master"
# turn off learning and flooding in SW
-simp ssh tut sw1 --cmd "sudo /sbin/bridge link set dev swp1 learning off"
-simp ssh tut sw1 --cmd "sudo /sbin/bridge link set dev swp2 learning off"
+simp ssh tut sw1 --cmd "sudo /sbin/bridge link set dev sw1p1 learning off"
+simp ssh tut sw1 --cmd "sudo /sbin/bridge link set dev sw1p2 learning off"
-simp ssh tut sw1 --cmd "sudo /sbin/bridge link set dev swp1 flood off"
-simp ssh tut sw1 --cmd "sudo /sbin/bridge link set dev swp2 flood off"
-
-# turn on learning in HW
-
-simp ssh tut sw1 --cmd "sudo /sbin/bridge link set dev swp1 learning on self"
-simp ssh tut sw1 --cmd "sudo /sbin/bridge link set dev swp2 learning on self"
+simp ssh tut sw1 --cmd "sudo /sbin/bridge link set dev sw1p1 flood off"
+simp ssh tut sw1 --cmd "sudo /sbin/bridge link set dev sw1p2 flood off"
# bring up bridge and ports
simp ssh tut sw1 --cmd "sudo ifconfig br0 up"
-simp ssh tut sw1 --cmd "sudo ifconfig swp1 up"
-simp ssh tut sw1 --cmd "sudo ifconfig swp2 up"
+simp ssh tut sw1 --cmd "sudo ifconfig sw1p1 up"
+simp ssh tut sw1 --cmd "sudo ifconfig sw1p2 up"
# config IP on host VLANs
-simp ssh tut h1 --cmd "sudo vconfig add swp1 57 >/dev/null 2>&1"
-simp ssh tut h1 --cmd "sudo ifconfig swp1 up"
-simp ssh tut h1 --cmd "sudo ifconfig swp1.57 11.0.0.1/24"
+simp ssh tut h1 --cmd "sudo vconfig add sw1p1 57 >/dev/null 2>&1"
+simp ssh tut h1 --cmd "sudo ifconfig sw1p1 up"
+simp ssh tut h1 --cmd "sudo ifconfig sw1p1.57 11.0.0.1/24"
-simp ssh tut h2 --cmd "sudo vconfig add swp1 57 >/dev/null 2>&1"
-simp ssh tut h2 --cmd "sudo ifconfig swp1 up"
-simp ssh tut h2 --cmd "sudo ifconfig swp1.57 11.0.0.2/24"
+simp ssh tut h2 --cmd "sudo vconfig add sw1p1 57 >/dev/null 2>&1"
+simp ssh tut h2 --cmd "sudo ifconfig sw1p1 up"
+simp ssh tut h2 --cmd "sudo ifconfig sw1p1.57 11.0.0.2/24"
# test...
diff --git a/tests/rocker/bridge-vlan-stp b/tests/rocker/bridge-vlan-stp
index 77ab67e..8170819 100755
--- a/tests/rocker/bridge-vlan-stp
+++ b/tests/rocker/bridge-vlan-stp
@@ -10,8 +10,8 @@ while ! simp ssh tut h2 --cmd "ping -c 1 localhost >/dev/null"; do sleep 1; done
simp ssh tut sw1 --cmd "sudo /sbin/ip link add name br0 type bridge"
simp ssh tut sw1 --cmd "sudo brctl stp br0 on"
-simp ssh tut sw1 --cmd "sudo /sbin/ip link set dev swp1 master br0"
-simp ssh tut sw1 --cmd "sudo /sbin/ip link set dev swp2 master br0"
+simp ssh tut sw1 --cmd "sudo /sbin/ip link set dev sw1p1 master br0"
+simp ssh tut sw1 --cmd "sudo /sbin/ip link set dev sw1p2 master br0"
# turn off vlan default_pvid on br0
# turn on vlan filtering on br0
@@ -21,37 +21,32 @@ simp ssh tut sw1 --cmd "echo 1 | sudo dd of=/sys/class/net/br0/bridge/vlan_filte
# add both ports to VLAN 57
-simp ssh tut sw1 --cmd "sudo /sbin/bridge vlan add vid 57 dev swp1 master"
-simp ssh tut sw1 --cmd "sudo /sbin/bridge vlan add vid 57 dev swp2 master"
+simp ssh tut sw1 --cmd "sudo /sbin/bridge vlan add vid 57 dev sw1p1 master"
+simp ssh tut sw1 --cmd "sudo /sbin/bridge vlan add vid 57 dev sw1p2 master"
# turn off learning and flooding in SW
-simp ssh tut sw1 --cmd "sudo /sbin/bridge link set dev swp1 learning off"
-simp ssh tut sw1 --cmd "sudo /sbin/bridge link set dev swp2 learning off"
+simp ssh tut sw1 --cmd "sudo /sbin/bridge link set dev sw1p1 learning off"
+simp ssh tut sw1 --cmd "sudo /sbin/bridge link set dev sw1p2 learning off"
-simp ssh tut sw1 --cmd "sudo /sbin/bridge link set dev swp1 flood off"
-simp ssh tut sw1 --cmd "sudo /sbin/bridge link set dev swp2 flood off"
-
-# turn on learning in HW
-
-simp ssh tut sw1 --cmd "sudo /sbin/bridge link set dev swp1 learning on self"
-simp ssh tut sw1 --cmd "sudo /sbin/bridge link set dev swp2 learning on self"
+simp ssh tut sw1 --cmd "sudo /sbin/bridge link set dev sw1p1 flood off"
+simp ssh tut sw1 --cmd "sudo /sbin/bridge link set dev sw1p2 flood off"
# config IP on host VLANs
-simp ssh tut h1 --cmd "sudo vconfig add swp1 57 >/dev/null 2>&1"
-simp ssh tut h1 --cmd "sudo ifconfig swp1 up"
-simp ssh tut h1 --cmd "sudo ifconfig swp1.57 11.0.0.1/24"
+simp ssh tut h1 --cmd "sudo vconfig add sw1p1 57 >/dev/null 2>&1"
+simp ssh tut h1 --cmd "sudo ifconfig sw1p1 up"
+simp ssh tut h1 --cmd "sudo ifconfig sw1p1.57 11.0.0.1/24"
-simp ssh tut h2 --cmd "sudo vconfig add swp1 57 >/dev/null 2>&1"
-simp ssh tut h2 --cmd "sudo ifconfig swp1 up"
-simp ssh tut h2 --cmd "sudo ifconfig swp1.57 11.0.0.2/24"
+simp ssh tut h2 --cmd "sudo vconfig add sw1p1 57 >/dev/null 2>&1"
+simp ssh tut h2 --cmd "sudo ifconfig sw1p1 up"
+simp ssh tut h2 --cmd "sudo ifconfig sw1p1.57 11.0.0.2/24"
# bring up bridge and ports
simp ssh tut sw1 --cmd "sudo ifconfig br0 up"
-simp ssh tut sw1 --cmd "sudo ifconfig swp1 up"
-simp ssh tut sw1 --cmd "sudo ifconfig swp2 up"
+simp ssh tut sw1 --cmd "sudo ifconfig sw1p1 up"
+simp ssh tut sw1 --cmd "sudo ifconfig sw1p2 up"
# test...
diff --git a/tests/rocker/port b/tests/rocker/port
index 3437f7d..5f2c248 100755
--- a/tests/rocker/port
+++ b/tests/rocker/port
@@ -7,13 +7,13 @@ while ! simp ssh tut h2 --cmd "ping -c 1 localhost >/dev/null"; do sleep 1; done
# bring up DUT ports
-simp ssh tut sw1 --cmd "sudo ifconfig swp1 11.0.0.1/24"
-simp ssh tut sw1 --cmd "sudo ifconfig swp2 12.0.0.1/24"
+simp ssh tut sw1 --cmd "sudo ifconfig sw1p1 11.0.0.1/24"
+simp ssh tut sw1 --cmd "sudo ifconfig sw1p2 12.0.0.1/24"
# config IP on hosts
-simp ssh tut h1 --cmd "sudo ifconfig swp1 11.0.0.2/24"
-simp ssh tut h2 --cmd "sudo ifconfig swp1 12.0.0.2/24"
+simp ssh tut h1 --cmd "sudo ifconfig sw1p1 11.0.0.2/24"
+simp ssh tut h2 --cmd "sudo ifconfig sw1p1 12.0.0.2/24"
# test...
--
1.7.10.4
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [Qemu-devel] [PATCH v3 3/4] rocker: bring link up/down on PHY enable/disable
2015-05-29 14:01 [Qemu-devel] [PATCH v3 0/4] rocker device updates sfeldma
2015-05-29 14:01 ` [Qemu-devel] [PATCH v3 1/4] rocker: Add support for phys name sfeldma
2015-05-29 14:01 ` [Qemu-devel] [PATCH v3 2/4] rocker: update tests using hw-derived interface names sfeldma
@ 2015-05-29 14:01 ` sfeldma
2015-05-29 14:01 ` [Qemu-devel] [PATCH v3 4/4] qmp/hmp: add rocker device support sfeldma
2015-06-02 15:09 ` [Qemu-devel] [PATCH v3 0/4] rocker device updates Stefan Hajnoczi
4 siblings, 0 replies; 9+ messages in thread
From: sfeldma @ 2015-05-29 14:01 UTC (permalink / raw)
To: qemu-devel; +Cc: stefanha, jiri, dsahern
From: Scott Feldman <sfeldma@gmail.com>
When the OS driver enables/disables the port, go ahead and set the port's
link status to up/down in response to the change. This more closely
emulates real hardware when the PHY for the port is brought up/down
and the PHY negotiates carrier (link status) with link partner. In
the case of qemu, the virtual rocker device can't really do link
negotiation with the link partner as that requires signally over a
physical medium (the wire), so just pretend the negotiation was
successful and bring the link up when the port is enabled.
Signed-off-by: Scott Feldman <sfeldma@gmail.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
---
hw/net/rocker/rocker_fp.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/hw/net/rocker/rocker_fp.c b/hw/net/rocker/rocker_fp.c
index 393e9e7..29a2b68 100644
--- a/hw/net/rocker/rocker_fp.c
+++ b/hw/net/rocker/rocker_fp.c
@@ -178,8 +178,19 @@ bool fp_port_enabled(FpPort *port)
return port->enabled;
}
+static void fp_port_set_link(FpPort *port, bool up)
+{
+ NetClientState *nc = qemu_get_queue(port->nic);
+
+ if (up == nc->link_down) {
+ nc->link_down = !up;
+ nc->info->link_status_changed(nc);
+ }
+}
+
void fp_port_enable(FpPort *port)
{
+ fp_port_set_link(port, true);
port->enabled = true;
DPRINTF("port %d enabled\n", port->index);
}
@@ -187,6 +198,7 @@ void fp_port_enable(FpPort *port)
void fp_port_disable(FpPort *port)
{
port->enabled = false;
+ fp_port_set_link(port, false);
DPRINTF("port %d disabled\n", port->index);
}
--
1.7.10.4
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [Qemu-devel] [PATCH v3 4/4] qmp/hmp: add rocker device support
2015-05-29 14:01 [Qemu-devel] [PATCH v3 0/4] rocker device updates sfeldma
` (2 preceding siblings ...)
2015-05-29 14:01 ` [Qemu-devel] [PATCH v3 3/4] rocker: bring link up/down on PHY enable/disable sfeldma
@ 2015-05-29 14:01 ` sfeldma
2015-06-02 15:07 ` Stefan Hajnoczi
2015-06-02 16:32 ` Eric Blake
2015-06-02 15:09 ` [Qemu-devel] [PATCH v3 0/4] rocker device updates Stefan Hajnoczi
4 siblings, 2 replies; 9+ messages in thread
From: sfeldma @ 2015-05-29 14:01 UTC (permalink / raw)
To: qemu-devel; +Cc: stefanha, jiri, dsahern
From: Scott Feldman <sfeldma@gmail.com>
v3:
Address review comments from Stefan Hajnoczi:
- Add missing hw/net/rocker/qmp-norocker.c file.
- Add missing curly brackets to a for loop
v2:
Address review comments from Stefan Hajnoczi:
- Add missing qapi/rocker.json file.
- Use PRIx64 for print uint64 value
- when CONFIG_ROCKER is not defined, build qmp-norocker.o stub using
hw/net/Makefile.objs rather than in the top-level Makefile.target
Change qapi/rocker.json "since 2.3" comments to "since 2.4", since qmp/hmp
support didn't get into 2.3.
v1:
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 lport 1 vlan 1 LLDP src 00:02:00:00:02:00 dst 01:80:c2:00:00:0e
2 60 lport 1 vlan 1 ARP src 00:02:00:00:02:00 dst 00:02:00:00:03:00
2 60 lport 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 lport 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 lport 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 lport 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 lport 1 vlan 1 IP src 00:02:00:00:02:00 dst 00:02:00:00:03:00 proto 1
2 60 lport 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 lport 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 lport 2 vlan 2 LLDP src <any> dst 01:80:c2:00:00:0e --> write group 0x02000000
1 60 6 lport 2 vlan 2 IPv6 src <any> dst <any> --> write group 0x02000000
1 60 174 lport 1 vlan 1 LLDP src <any> dst 01:80:c2:00:00:0e --> write group 0x01000000
1 60 174 lport 2 vlan 2 IP src <any> dst <any> --> write group 0x02000000
1 60 6 lport 1 vlan 1 IPv6 src <any> dst <any> --> write group 0x01000000
1 60 181 lport 2 vlan 2 ARP src <any> dst <any> --> write group 0x02000000
1 10 715 lport 2 --> apply new vlan 2 goto tbl 20
1 60 177 lport 1 vlan 1 ARP src <any> dst <any> --> write group 0x01000000
1 60 174 lport 1 vlan 1 IP src <any> dst <any> --> write group 0x01000000
1 10 717 lport 1 --> apply new vlan 1 goto tbl 20
1 0 1432 lport 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 lport 1) --> pop vlan out lport 1
0x01000002 (type L2 interface vlan 1 lport 2) --> pop vlan out lport 2
0x02000000 (type L2 interface vlan 2 lport 0) --> pop vlan out lport 0
0x01000000 (type L2 interface vlan 1 lport 0) --> pop vlan out lport 0
0x31000000 (type L2 multicast vlan 1 index 0) --> groups [0x01000002,0x01000000]
Signed-off-by: Scott Feldman <sfeldma@gmail.com>
Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
hmp-commands.hx | 24 ++++
hmp.c | 303 +++++++++++++++++++++++++++++++++++++++
hmp.h | 4 +
hw/net/Makefile.objs | 1 +
hw/net/rocker/qmp-norocker.c | 50 +++++++
hw/net/rocker/rocker.c | 45 ++++++
hw/net/rocker/rocker_fp.c | 10 ++
hw/net/rocker/rocker_fp.h | 1 +
hw/net/rocker/rocker_of_dpa.c | 312 +++++++++++++++++++++++++++++++++++++++++
monitor.c | 28 ++++
qapi-schema.json | 3 +
qapi/rocker.json | 286 +++++++++++++++++++++++++++++++++++++
qmp-commands.hx | 97 +++++++++++++
13 files changed, 1164 insertions(+)
create mode 100644 hw/net/rocker/qmp-norocker.c
create mode 100644 qapi/rocker.json
diff --git a/hmp-commands.hx b/hmp-commands.hx
index e864a6c..f8bc4fa 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1803,5 +1803,29 @@ 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
diff --git a/hmp.c b/hmp.c
index e17852d..7d771f1 100644
--- a/hmp.c
+++ b/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"
@@ -1976,3 +1977,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 %-4ld",
+ 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);
+}
diff --git a/hmp.h b/hmp.h
index a158e3f..bce3545 100644
--- a/hmp.h
+++ b/hmp.h
@@ -122,5 +122,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
diff --git a/hw/net/Makefile.objs b/hw/net/Makefile.objs
index 7b91c4e..9880173 100644
--- a/hw/net/Makefile.objs
+++ b/hw/net/Makefile.objs
@@ -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
diff --git a/hw/net/rocker/qmp-norocker.c b/hw/net/rocker/qmp-norocker.c
new file mode 100644
index 0000000..f253747
--- /dev/null
+++ b/hw/net/rocker/qmp-norocker.c
@@ -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;
+};
diff --git a/hw/net/rocker/rocker.c b/hw/net/rocker/rocker.c
index e74c027..4d25842 100644
--- a/hw/net/rocker/rocker.c
+++ b/hw/net/rocker/rocker.c
@@ -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;
diff --git a/hw/net/rocker/rocker_fp.c b/hw/net/rocker/rocker_fp.c
index 29a2b68..d8d934c 100644
--- a/hw/net/rocker/rocker_fp.c
+++ b/hw/net/rocker/rocker_fp.c
@@ -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));
diff --git a/hw/net/rocker/rocker_fp.h b/hw/net/rocker/rocker_fp.h
index 92a6861..ab80fd8 100644
--- a/hw/net/rocker/rocker_fp.h
+++ b/hw/net/rocker/rocker_fp.h
@@ -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);
diff --git a/hw/net/rocker/rocker_of_dpa.c b/hw/net/rocker/rocker_of_dpa.c
index 1bcb7af..b25a17d 100644
--- a/hw/net/rocker/rocker_of_dpa.c
+++ b/hw/net/rocker/rocker_of_dpa.c
@@ -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,
diff --git a/monitor.c b/monitor.c
index b2561e1..2df8943 100644
--- a/monitor.c
+++ b/monitor.c
@@ -2936,6 +2936,34 @@ static mon_cmd_t info_cmds[] = {
.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,
},
};
diff --git a/qapi-schema.json b/qapi-schema.json
index 9c92482..5c47a4f 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -3759,3 +3759,6 @@
# Since: 2.1
##
{ 'command': 'rtc-reset-reinjection' }
+
+# Rocker ethernet network switch
+{ 'include': 'qapi/rocker.json' }
diff --git a/qapi/rocker.json b/qapi/rocker.json
new file mode 100644
index 0000000..ee380ee
--- /dev/null
+++ b/qapi/rocker.json
@@ -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' } }
+
+##
+# @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' } }
+
+##
+# @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' } }
+
+##
+# @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' } }
+
+##
+# @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'] }
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 7506774..bbdb94f 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -4162,3 +4162,100 @@ 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}
+ ]}
--
1.7.10.4
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [Qemu-devel] [PATCH v3 4/4] qmp/hmp: add rocker device support
2015-05-29 14:01 ` [Qemu-devel] [PATCH v3 4/4] qmp/hmp: add rocker device support sfeldma
@ 2015-06-02 15:07 ` Stefan Hajnoczi
2015-06-02 16:32 ` Eric Blake
1 sibling, 0 replies; 9+ messages in thread
From: Stefan Hajnoczi @ 2015-06-02 15:07 UTC (permalink / raw)
To: sfeldma; +Cc: jiri, qemu-devel, dsahern
[-- Attachment #1: Type: text/plain, Size: 1145 bytes --]
On Fri, May 29, 2015 at 07:01:49AM -0700, sfeldma@gmail.com wrote:
> +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 %-4ld",
> + key->priority, key->tbl_id, flow->hits);
flow->hits is uint64_t so I changed the format string to use %-4" PRIu64
when merging the patches. This way it compiles cleanly on 32-bit hosts.
[-- Attachment #2: Type: application/pgp-signature, Size: 473 bytes --]
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Qemu-devel] [PATCH v3 0/4] rocker device updates
2015-05-29 14:01 [Qemu-devel] [PATCH v3 0/4] rocker device updates sfeldma
` (3 preceding siblings ...)
2015-05-29 14:01 ` [Qemu-devel] [PATCH v3 4/4] qmp/hmp: add rocker device support sfeldma
@ 2015-06-02 15:09 ` Stefan Hajnoczi
4 siblings, 0 replies; 9+ messages in thread
From: Stefan Hajnoczi @ 2015-06-02 15:09 UTC (permalink / raw)
To: sfeldma; +Cc: jiri, qemu-devel, dsahern
[-- Attachment #1: Type: text/plain, Size: 2572 bytes --]
On Fri, May 29, 2015 at 07:01:45AM -0700, sfeldma@gmail.com wrote:
> From: Scott Feldman <sfeldma@gmail.com>
>
> v3:
>
> Address review comments from Stefan Hajnoczi:
>
> - Add missing hw/net/rocker/qmp-norocker.c file.
> - Add missing curly brackets to a for loop
>
> v2:
>
> Address some review comments by Stefan Hajnoczi: see individual patches for
> v1->v2 changes.
>
> v1:
>
> Some rocker device updates we've been holding onto waiting for base rocker
> device to be pulled into 2.4. David added support for the device to return the
> physical port name, which in turn can be used by the OS to name the interface.
> I added a small change the bringe link up/down when port is enabled/disabled.
>
> The big addition is adding qmp/hmp support to rocker. This was included in the
> original rocker device patch set, but pulled as there where last-minute issues
> with building on non-PCI targets. These issues have been addressed by stubbing
> out qmp/hmp support when rocker device is built for non-PCI targets.
>
> David Ahern (1):
> rocker: Add support for phys name
>
> Scott Feldman (3):
> rocker: update tests using hw-derived interface names
> rocker: bring link up/down on PHY enable/disable
> qmp/hmp: add rocker device support
>
> docs/specs/rocker.txt | 1 +
> hmp-commands.hx | 24 ++++
> hmp.c | 303 +++++++++++++++++++++++++++++++++++++++
> hmp.h | 4 +
> hw/net/Makefile.objs | 1 +
> hw/net/rocker/qmp-norocker.c | 50 +++++++
> hw/net/rocker/rocker.c | 68 ++++++++-
> hw/net/rocker/rocker_fp.c | 29 +++-
> hw/net/rocker/rocker_fp.h | 2 +
> hw/net/rocker/rocker_hw.h | 1 +
> hw/net/rocker/rocker_of_dpa.c | 312 +++++++++++++++++++++++++++++++++++++++++
> monitor.c | 28 ++++
> qapi-schema.json | 3 +
> qapi/rocker.json | 286 +++++++++++++++++++++++++++++++++++++
> qmp-commands.hx | 97 +++++++++++++
> tests/rocker/bridge | 25 ++--
> tests/rocker/bridge-stp | 25 ++--
> tests/rocker/bridge-vlan | 37 +++--
> tests/rocker/bridge-vlan-stp | 37 +++--
> tests/rocker/port | 8 +-
> 20 files changed, 1263 insertions(+), 78 deletions(-)
> create mode 100644 hw/net/rocker/qmp-norocker.c
> create mode 100644 qapi/rocker.json
Thanks, applied to my master tree:
https://github.com/stefanha/qemu/commits/master
Stefan
[-- Attachment #2: Type: application/pgp-signature, Size: 473 bytes --]
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Qemu-devel] [PATCH v3 1/4] rocker: Add support for phys name
2015-05-29 14:01 ` [Qemu-devel] [PATCH v3 1/4] rocker: Add support for phys name sfeldma
@ 2015-06-02 16:27 ` Eric Blake
0 siblings, 0 replies; 9+ messages in thread
From: Eric Blake @ 2015-06-02 16:27 UTC (permalink / raw)
To: sfeldma, qemu-devel; +Cc: stefanha, jiri, dsahern
[-- Attachment #1: Type: text/plain, Size: 1272 bytes --]
On 05/29/2015 08:01 AM, sfeldma@gmail.com wrote:
> From: David Ahern <dsahern@gmail.com>
>
> v2:
>
> Review comment from Stefan Hajnoczi:
>
> - use private ROCKER_IFNAMSIZ = 16 to avoid breaking Windows build
> as Windows does not include <net/if.h>
>
> v1:
>
> Add ROCKER_TLV_CMD_PORT_SETTINGS_PHYS_NAME to port settings. This attribute
> exports the port name to the guest OS allowing it to name interfaces with
> sensible defaults.
The above patch version information...
>
> Mostly done by Scott for phys_id support; adapted to phys_name by David.
>
> Signed-off-by: Scott Feldman <sfeldma@gmail.com>
> Signed-off-by: David Ahern <dsahern@gmail.com>
> ---
...belongs better here, after the --- separator. 'git am' strips off
anything in this location, which makes for a nice separation: anything
before the separator should be stand-alone, but things that are useful
to list readers but not to permanent git history should be after the
separator. After all, a year from now, we won't care if it took 1 or 10
versions on the list for the patch that got accepted, we will only care
about the one version in git.
--
Eric Blake eblake redhat com +1-919-301-3266
Libvirt virtualization library http://libvirt.org
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Qemu-devel] [PATCH v3 4/4] qmp/hmp: add rocker device support
2015-05-29 14:01 ` [Qemu-devel] [PATCH v3 4/4] qmp/hmp: add rocker device support sfeldma
2015-06-02 15:07 ` Stefan Hajnoczi
@ 2015-06-02 16:32 ` Eric Blake
1 sibling, 0 replies; 9+ messages in thread
From: Eric Blake @ 2015-06-02 16:32 UTC (permalink / raw)
To: sfeldma, qemu-devel; +Cc: stefanha, jiri, dsahern
[-- Attachment #1: Type: text/plain, Size: 3116 bytes --]
On 05/29/2015 08:01 AM, sfeldma@gmail.com wrote:
> From: Scott Feldman <sfeldma@gmail.com>
>
> v3:
>
> Address review comments from Stefan Hajnoczi:
>
> - Add missing hw/net/rocker/qmp-norocker.c file.
> - Add missing curly brackets to a for loop
>
> v2:
>
> Address review comments from Stefan Hajnoczi:
>
> - Add missing qapi/rocker.json file.
> - Use PRIx64 for print uint64 value
> - when CONFIG_ROCKER is not defined, build qmp-norocker.o stub using
> hw/net/Makefile.objs rather than in the top-level Makefile.target
>
> Change qapi/rocker.json "since 2.3" comments to "since 2.4", since qmp/hmp
> support didn't get into 2.3.
>
> v1:
Again, version info belongs after ---.
>
> 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
>
> +++ b/qapi/rocker.json
> +##
> +# @rocker:
This comment...
> +#
> +# Return rocker switch information.
> +#
> +# Returns: @Rocker information
> +#
> +# Since: 2.4
> +##
> +{ 'command': 'query-rocker',
...does not match this command name.
> +
> +##
> +# @rocker-ports:
> +#
> +# Return rocker switch information.
> +#
> +# Returns: @Rocker information
> +#
> +# Since: 2.4
> +##
> +{ 'command': 'query-rocker-ports',
and again.
> +
> +##
> +# @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',
And again.
> +##
> +# @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',
and again.
> +++ b/qmp-commands.hx
> +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}
You might want to wrap these long lines.
--
Eric Blake eblake redhat com +1-919-301-3266
Libvirt virtualization library http://libvirt.org
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2015-06-02 16:32 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-05-29 14:01 [Qemu-devel] [PATCH v3 0/4] rocker device updates sfeldma
2015-05-29 14:01 ` [Qemu-devel] [PATCH v3 1/4] rocker: Add support for phys name sfeldma
2015-06-02 16:27 ` Eric Blake
2015-05-29 14:01 ` [Qemu-devel] [PATCH v3 2/4] rocker: update tests using hw-derived interface names sfeldma
2015-05-29 14:01 ` [Qemu-devel] [PATCH v3 3/4] rocker: bring link up/down on PHY enable/disable sfeldma
2015-05-29 14:01 ` [Qemu-devel] [PATCH v3 4/4] qmp/hmp: add rocker device support sfeldma
2015-06-02 15:07 ` Stefan Hajnoczi
2015-06-02 16:32 ` Eric Blake
2015-06-02 15:09 ` [Qemu-devel] [PATCH v3 0/4] rocker device updates Stefan Hajnoczi
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).