diff options
Diffstat (limited to 'hw/net/rocker/rocker.c')
-rw-r--r-- | hw/net/rocker/rocker.c | 68 |
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++); |