summary refs log tree commit diff stats
path: root/hw/net/rocker/rocker.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/net/rocker/rocker.c')
-rw-r--r--hw/net/rocker/rocker.c68
1 files changed, 67 insertions, 1 deletions
diff --git a/hw/net/rocker/rocker.c b/hw/net/rocker/rocker.c
index 55b6c46157..4d25842509 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;
@@ -238,6 +283,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 +311,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 +320,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 +338,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 +1327,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++);