From 8536afae6f8ff3196aa8457cc0a53c5c0ea9fbac Mon Sep 17 00:00:00 2001 From: John Crispin Date: Wed, 23 Dec 2015 19:24:45 +0000 Subject: [PATCH] swconfig: support receiving SWITCH_TYPE_LINK from kernel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When using cli, print link state the same way kernel used to do it. This will allow kernel switching PORT_LINK from SWITCH_TYPE_STRING. Signed-off-by: Rafał Miłecki SVN-Revision: 47998 --- package/network/config/swconfig/src/cli.c | 33 ++++++++++++++++ package/network/config/swconfig/src/swlib.c | 42 +++++++++++++++++++++ package/network/config/swconfig/src/swlib.h | 17 +++++++++ 3 files changed, 92 insertions(+) diff --git a/package/network/config/swconfig/src/cli.c b/package/network/config/swconfig/src/cli.c index d472086781..90554143e1 100644 --- a/package/network/config/swconfig/src/cli.c +++ b/package/network/config/swconfig/src/cli.c @@ -84,9 +84,27 @@ list_attributes(struct switch_dev *dev) print_attrs(dev->port_ops); } +static const char * +speed_str(int speed) +{ + switch (speed) { + case 10: + return "10baseT"; + case 100: + return "100baseT"; + case 1000: + return "1000baseT"; + default: + break; + } + + return "unknown"; +} + static void print_attr_val(const struct switch_attr *attr, const struct switch_val *val) { + struct switch_port_link *link; int i; switch (attr->type) { @@ -104,6 +122,21 @@ print_attr_val(const struct switch_attr *attr, const struct switch_val *val) SWLIB_PORT_FLAG_TAGGED) ? "t" : ""); } break; + case SWITCH_TYPE_LINK: + link = val->value.link; + if (link->link) + printf("port:%d link:up speed:%s %s-duplex %s%s%s%s%s", + val->port_vlan, + speed_str(link->speed), + link->duplex ? "full" : "half", + link->tx_flow ? "txflow " : "", + link->rx_flow ? "rxflow " : "", + link->eee & SWLIB_LINK_FLAG_EEE_100BASET ? "eee100 " : "", + link->eee & SWLIB_LINK_FLAG_EEE_1000BASET ? "eee1000 " : "", + link->aneg ? "auto" : ""); + else + printf("port:%d link:down", val->port_vlan); + break; default: printf("?unknown-type?"); } diff --git a/package/network/config/swconfig/src/swlib.c b/package/network/config/swconfig/src/swlib.c index 0dbace551e..908e0fb496 100644 --- a/package/network/config/swconfig/src/swlib.c +++ b/package/network/config/swconfig/src/swlib.c @@ -51,6 +51,15 @@ static struct nla_policy portmap_policy[SWITCH_PORTMAP_MAX] = { [SWITCH_PORTMAP_VIRT] = { .type = NLA_U32 }, }; +static struct nla_policy link_policy[SWITCH_LINK_ATTR_MAX] = { + [SWITCH_LINK_FLAG_LINK] = { .type = NLA_FLAG }, + [SWITCH_LINK_FLAG_DUPLEX] = { .type = NLA_FLAG }, + [SWITCH_LINK_FLAG_ANEG] = { .type = NLA_FLAG }, + [SWITCH_LINK_SPEED] = { .type = NLA_U32 }, + [SWITCH_LINK_FLAG_EEE_100BASET] = { .type = NLA_FLAG }, + [SWITCH_LINK_FLAG_EEE_1000BASET] = { .type = NLA_FLAG }, +}; + static inline void * swlib_alloc(size_t size) { @@ -201,6 +210,37 @@ out: return err; } +static int +store_link_val(struct nl_msg *msg, struct nlattr *nla, struct switch_val *val) +{ + struct nlattr *tb[SWITCH_LINK_ATTR_MAX + 1]; + struct switch_port_link *link; + int err = 0; + + if (!val->value.link) + val->value.link = malloc(sizeof(struct switch_port_link)); + + err = nla_parse_nested(tb, SWITCH_LINK_ATTR_MAX, nla, link_policy); + if (err < 0) + goto out; + + link = val->value.link; + link->link = !!tb[SWITCH_LINK_FLAG_LINK]; + link->duplex = !!tb[SWITCH_LINK_FLAG_DUPLEX]; + link->aneg = !!tb[SWITCH_LINK_FLAG_ANEG]; + link->tx_flow = !!tb[SWITCH_LINK_FLAG_TX_FLOW]; + link->rx_flow = !!tb[SWITCH_LINK_FLAG_RX_FLOW]; + link->speed = nla_get_u32(tb[SWITCH_LINK_SPEED]); + link->eee = 0; + if (tb[SWITCH_LINK_FLAG_EEE_100BASET]) + link->eee |= SWLIB_LINK_FLAG_EEE_100BASET; + if (tb[SWITCH_LINK_FLAG_EEE_1000BASET]) + link->eee |= SWLIB_LINK_FLAG_EEE_1000BASET; + +out: + return err; +} + static int store_val(struct nl_msg *msg, void *arg) { @@ -221,6 +261,8 @@ store_val(struct nl_msg *msg, void *arg) val->value.s = strdup(nla_get_string(tb[SWITCH_ATTR_OP_VALUE_STR])); else if (tb[SWITCH_ATTR_OP_VALUE_PORTS]) val->err = store_port_val(msg, tb[SWITCH_ATTR_OP_VALUE_PORTS], val); + else if (tb[SWITCH_ATTR_OP_VALUE_LINK]) + val->err = store_link_val(msg, tb[SWITCH_ATTR_OP_VALUE_LINK], val); val->err = 0; return 0; diff --git a/package/network/config/swconfig/src/swlib.h b/package/network/config/swconfig/src/swlib.h index 7edece3cc6..f443bf5c26 100644 --- a/package/network/config/swconfig/src/swlib.h +++ b/package/network/config/swconfig/src/swlib.h @@ -105,11 +105,16 @@ enum swlib_port_flags { SWLIB_PORT_FLAG_TAGGED = (1 << 0), }; +enum swlib_link_flags { + SWLIB_LINK_FLAG_EEE_100BASET = (1 << 0), + SWLIB_LINK_FLAG_EEE_1000BASET = (1 << 1), +}; struct switch_dev; struct switch_attr; struct switch_port; struct switch_port_map; +struct switch_port_link; struct switch_val; struct uci_package; @@ -138,6 +143,7 @@ struct switch_val { char *s; int i; struct switch_port *ports; + struct switch_port_link *link; } value; }; @@ -161,6 +167,17 @@ struct switch_portmap { char *segment; }; +struct switch_port_link { + int link:1; + int duplex:1; + int aneg:1; + int tx_flow:1; + int rx_flow:1; + int speed; + /* in ethtool adv_t format */ + uint32_t eee; +}; + /** * swlib_list: list all switches */