/* * ethsw.c - implements APIs through swlib * * Copyright (C) 2018 iopsys Software Solutions AB. All rights reserved. * * Author: anjan.chanda@iopsys.eu * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. * * 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include <string.h> #include <ctype.h> #include <unistd.h> #include <fcntl.h> #include <sys/ioctl.h> #include <sys/socket.h> #include <sys/types.h> //#include <net/if.h> #include <linux/if.h> #include <stdbool.h> #include <linux/mii.h> #include <linux/netlink.h> #include <linux/switch.h> #include <swlib.h> #include "ethernet.h" #define UNUSED(var) (void)(var) #define ETHSW_NAME "switch0" int ethsw_get_link_settings(char *name, struct eth_link *link) { struct switch_dev *sw_dev; struct switch_attr *attr; struct switch_val val; struct switch_port_link *l; int port = ETH_PORT_UNDEFINED; if (link->portid != ETH_PORT_UNDEFINED) port = link->portid; //eth_get_port_data(name, PORT_TYPE_NUMBER); // TODO ? if (port == ETH_PORT_UNDEFINED) return -1; sw_dev = swlib_connect(ETHSW_NAME); if (!sw_dev) return -1; swlib_scan(sw_dev); val.port_vlan = port; attr = swlib_lookup_attr(sw_dev, SWLIB_ATTR_GROUP_PORT, "link"); if (attr->type != SWITCH_TYPE_LINK){ swlib_free_all(sw_dev); return -1; } swlib_get_attr(sw_dev, attr, &val); l = val.value.link; if (l->link){ link->autoneg = l->aneg; link->fullduplex = l->duplex; link->speed = l->speed; link->down = 0; } else { link->autoneg = 0; link->fullduplex = 0; link->speed = 0; link->down = 1; } swlib_free_all(sw_dev); return 0; } int ethsw_set_link_settings(char *name, struct eth_link link) { struct switch_dev *sw_dev; struct switch_attr *attr; struct switch_val val; struct switch_port_link l; int port = ETH_PORT_UNDEFINED; libethernet_dbg("%s(): name = %s\n", __func__, name); if (link.portid != ETH_PORT_UNDEFINED) port = link.portid; //eth_get_port_data(name, PORT_TYPE_NUMBER); // TODO ? if (port == ETH_PORT_UNDEFINED) return -1; sw_dev = swlib_connect(ETHSW_NAME); if (!sw_dev) return -1; swlib_scan(sw_dev); val.port_vlan = port; attr = swlib_lookup_attr(sw_dev, SWLIB_ATTR_GROUP_PORT, "link"); if (attr->type != SWITCH_TYPE_LINK){ swlib_free_all(sw_dev); return -1; } memset(&l, 0, sizeof(struct switch_port_link)); l.duplex = link.fullduplex; l.aneg = link.autoneg; l.speed = link.speed; val.value.link = &l; swlib_set_attr(sw_dev, attr, &val); swlib_free_all(sw_dev); return 0; } int ethsw_poweron_phy(char *name, struct eth_phy p) { return 0; } int ethsw_poweroff_phy(char *name, struct eth_phy p) { return 0; } const struct eth_ops ethsw_ops = { .name = "eth", //.up = ethsw_up, //.down = ethsw_down, .set_link_settings = ethsw_set_link_settings, .get_link_settings = ethsw_get_link_settings, //.get_stats = ethsw_get_stats, .poweron_phy = ethsw_poweron_phy, .poweroff_phy = ethsw_poweroff_phy, };