/* // Copyright (c) 2017 Intel Corporation // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. */ #ifndef INTERFACE_H #define INTERFACE_H #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdint.h> #include <inttypes.h> #include <sys/types.h> #include <sys/queue.h> #include <netinet/in.h> #include <setjmp.h> #include <stdarg.h> #include <ctype.h> #include <errno.h> #include <getopt.h> #include <signal.h> #include <stdbool.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <rte_common.h> #include <rte_log.h> #include <rte_malloc.h> #include <rte_memory.h> #include <rte_memcpy.h> #include <rte_memzone.h> #include <rte_eal.h> #include <rte_per_lcore.h> #include <rte_launch.h> #include <rte_atomic.h> #include <rte_cycles.h> #include <rte_prefetch.h> #include <rte_lcore.h> #include <rte_per_lcore.h> #include <rte_branch_prediction.h> #include <rte_interrupts.h> #include <rte_pci.h> #include <rte_random.h> #include <rte_debug.h> #include <rte_ether.h> #include <rte_ethdev.h> #include <rte_ring.h> #include <rte_mempool.h> #include <rte_mbuf.h> #include <rte_eth_ctrl.h> #include <rte_errno.h> #include <rte_port_ethdev.h> #include <rte_eth_bond.h> #include <rte_rwlock.h> #define RTE_LOGTYPE_IFM RTE_LOGTYPE_USER1 #define IFM_SUCCESS 0 #define IFM_FAILURE -1 /* * IFM Ether link related macros */ #define IFM_ETH_LINK_HALF_DUPLEX 0 #define IFM_ETH_LINK_FULL_DUPLEX 1 #define IFM_ETH_LINK_DOWN 0 #define IFM_ETH_LINK_UP 1 #define IFM_ETH_LINK_FIXED 0 /* * Bonding */ #define IFM_SLAVE (1<<0) #define IFM_MASTER (1<<1) #define IFM_BONDED (1<<2) #define IFM_IPV4_ENABLED (1<<3) #define IFM_IPV6_ENABLED (1<<4) #define IFM_BONDING_MODE_ROUND_ROBIN 0 #define IFM_BONDING_MODE_ACTIVE_BACKUP 1 #define IFM_BONDING_MODE_BALANCE 2 #define IFM_BONDING_MODE_BROADCAST 3 #define IFM_BONDING_MODE_8023AD 4 #define IFM_BONDING_MODE_TLB 5 #define IFM_BONDING_MODE_ALB 6 #define IFM_BALANCE_XMIT_POLICY_LAYER2 0 #define IFM_BALANCE_XMIT_POLICY_LAYER23 1 #define IFM_BALANCE_XMIT_POLICY_LAYER34 2 /* * Queue related macros */ #define IFM_QUEUE_STAT_CNTRS 16 #define IFM_TX_DEFAULT_Q 0 #define IFM_RX_DEFAULT_Q 0 #define IFM_RX_DESC_DEFAULT 128 #define IFM_TX_DESC_DEFAULT 512 #define IFM_BURST_SIZE 32 #define IFM_BURST_TX_WAIT_US 1 #define IFM_BURST_TX_RETRIES 64 #define BURST_TX_DRAIN_US 100 /* * Misc */ #define IFM_IFNAME_LEN 16 #define IFM_CLIENT_NAME 20 #define IFM_MAX_CLIENT 10 #define IFM_ETHER_ADDR_SIZE 6 #define IFM_IPV6_ADDR_SIZE 16 #define IFM_DEBUG_CONFIG (1<<0) #define IFM_DEBUG_RXTX (1<<1) #define IFM_DEBUG_LOCKS (1<<2) #define IFM_DEBUG (1<<4) #define IFM_MAX_PORTARR_SZ 64 #define IFM_MAX_PORTARR_SZ 64 /** * Mempool configuration details: * Stores the mempool configuration information for the port. */ struct mempool_config { uint32_t pool_size;/**< The number of elements in the mempool.*/ uint32_t buffer_size; /**< The size of an element*/ uint32_t cache_size; /**< Cache size */ uint32_t cpu_socket_id; /**< The socket identifier in the case of NUMA.*/ } __rte_cache_aligned; /** * Port configuration: * Stores the configuration information for the port. * This structure is used during port and tx/rx queue setup. */ typedef struct _port_config_ { uint8_t port_id; /**< port id or pmd id to be configured */ int nrx_queue; /**< no of rx queues */ int ntx_queue; /**< no of tx queues */ uint32_t tx_buf_size; uint32_t state; /**< noshut/shut the admin state of the port*/ uint32_t promisc; /**< enable/diable promisc mode*/ struct mempool_config mempool; /**< Mempool configurations */ struct rte_eth_conf port_conf; /**< port configuration */ struct rte_eth_rxconf rx_conf; /**< rx queue configurations */ struct rte_eth_txconf tx_conf; /**< tx queue configurations */ } port_config_t; /** * Port statistics: * if_stats structure is a member variable of structure l2_phy_interface_t. * Used to maintain stats retreived from rte_eth_stats structure. */ typedef struct _if_stats_ { uint64_t rx_npkts;/**< Total number of successfully received packets.*/ uint64_t tx_npkts;/**< Total number of successfully transmitted bytes. */ uint64_t rx_bytes;/**< Total number of successfully received bytes.*/ uint64_t tx_bytes;/**< Total number of successfully transmitted bytes.*/ uint64_t rx_missed_pkts; /**< no of packets dropped by hw due because rx queues are full*/ uint64_t rx_err_pkts;/**< Total number of erroneous received packets. */ uint64_t rx_nobuf_fail;/**< Total number of RX mbuf allocation failures. */ uint64_t tx_failed_pkts;/**< Total number of failed transmitted packets.*/ uint64_t q_rxpkts[IFM_QUEUE_STAT_CNTRS];/**< Total number of queue RX packets.*/ uint64_t q_txpkts[IFM_QUEUE_STAT_CNTRS];/**< Total number of queue TX packets.*/ uint64_t q_rx_bytes[IFM_QUEUE_STAT_CNTRS]; /**< Total number of successfully received queue bytes.*/ uint64_t q_tx_bytes[IFM_QUEUE_STAT_CNTRS]; /**< Total number of successfully transmitted queue bytes.*/ uint64_t q_rx_pkt_drop[IFM_QUEUE_STAT_CNTRS]; /**<Total number of queue packets received that are dropped.*/ } __rte_cache_aligned if_stats; /** * structure to store bond port information */ struct bond_port { uint8_t bond_portid; /**<portid of the bond port.*/ uint8_t socket_id; /**<socketid of the port.*/ uint8_t mode; /**<mode config.*/ uint8_t xmit_policy; /**<xmit policy for this port.*/ uint32_t internal_ms; /**<in frequency.*/ uint32_t link_up_delay_ms; /**<frequency of informing linkup delay.*/ uint32_t link_down_delay_ms; /**<frequency of informing linkdown delay.*/ uint8_t primary; /**<primary port of this bond.*/ uint8_t slaves[RTE_MAX_ETHPORTS]; /**<list of slaves*/ int slave_count; /**<slave count.*/ uint8_t active_slaves[RTE_MAX_ETHPORTS]; /**<list of active slaves.*/ int active_slave_count; /**<cnt of active slave.*/ } __rte_cache_aligned; /** * Physical port details: * Used to store information about configured port. * Most of the member variables in this structure are populated * from struct rte_eth_dev_info */ typedef struct _l2_phy_interface_ { struct _l2_phy_interface_ *next; /**< pointer to physical interface list */ uint8_t pmdid; /**< populated from rth_eth_dev_info */ unsigned int if_index; /**< populated from rth_eth_dev_info */ char ifname[IFM_IFNAME_LEN]; /**< populated from rth_eth_dev_info */ uint16_t mtu; /**< mtu value - configurable */ uint8_t macaddr[IFM_ETHER_ADDR_SIZE]; /**< Ether addr*/ uint32_t promisc; /**< promisc mode - configurable*/ uint32_t flags; /**< Used for link bonding */ /* Link status */ uint32_t link_speed; /**< line speed */ uint16_t link_duplex:1; /**< duplex mode */ uint16_t link_autoneg:1; /**< auto negotiation*/ uint16_t link_status:1; /**< operational status */ uint16_t admin_status:1; /**< Admin status of a port*/ /* queue details */ struct rte_mempool *mempool; /**< HW Q*/ uint32_t min_rx_bufsize; /**< rx buffer size supported */ uint32_t max_rx_pktlen; /**< max size of packet*/ uint16_t max_rx_queues; /**< max number of rx queues supported */ uint16_t max_tx_queues; /**< max number queues supported*/ uint64_t n_rxpkts; /**< number of packets received */ uint64_t n_txpkts; /**< number of packets transmitted */ if_stats stats; /**< port stats - populated from rte_eth_ifstats */ uint16_t(*retrieve_bulk_pkts) (uint8_t, uint16_t, struct rte_mbuf **); /**< pointer to read packets*/ uint16_t(*transmit_bulk_pkts) (struct _l2_phy_interface_ *, struct rte_mbuf **, uint64_t); /**< pointer to transmit the bulk of packets */ int (*transmit_single_pkt) (struct _l2_phy_interface_ *, struct rte_mbuf *); /**< pointer to transmit the a single packet*/ struct rte_eth_dev_tx_buffer *tx_buffer; uint64_t tx_buf_len; /**< number of packets in tx_buf */ void *ipv4_list; /**< pointer to ip list */ void *ipv6_list; /**< pointer to ipv6 list */ struct bond_port *bond_config; /**< pointer to bond info*/ port_config_t port_config; } __rte_cache_aligned l2_phy_interface_t; /** * Port IPv4 address details: * Used to maintain IPv4 information of a port. */ typedef struct _ipv4list_ { struct _ipv4list_ *next;/**< pointer to IPv4 list */ uint32_t ipaddr; /**< Configured ipv4 address */ unsigned int addrlen; /**< subnet mask or addrlen */ unsigned int mtu; /**< IPv6 mtu*/ l2_phy_interface_t *port; /**< pointer to a port on which this ipaddr is configured*/ } ipv4list_t; /** * Port IPv6 address details: * Used to maintain IPv6 information of a port. */ typedef struct _ipv6list_ { struct _ipv6list_ *next; /**< Ptr IPv6 list */ uint8_t ipaddr[IFM_IPV6_ADDR_SIZE]; /**< Configured ipv6 address */ unsigned int addrlen; /**< subnet mask or addrlen*/ unsigned int mtu; /**< IPv6 mtu*/ l2_phy_interface_t *port; /**< ptr to a port on whicch ipv6 addr is configured*/ } ipv6list_t; /** * Interface Manager client details: * Maintains information about clients who registered for link status update. * Stores callback function to be called in case of link state change. */ typedef struct _ifm_client_ { uint32_t clientid; /**< unique client id identifies the client used for indexing*/ void (*cb_linkupdate) (uint8_t, unsigned int); /**< callback function to be triggered during an event*/ } __rte_cache_aligned ifm_client; /** * Interface manager global structure: * IFM main structure has pointer configured port list. */ typedef struct _interface_main_ { l2_phy_interface_t *port_list[IFM_MAX_PORTARR_SZ]; uint32_t nport_configured; /**< no of ports sucessfully configured during PCI probe*/ uint32_t nport_intialized; /**< no of ports sucessfully initialized through ifm_init*/ uint8_t nclient; /**< no of clients registered for Interface manager events*/ ifm_client if_client[IFM_MAX_CLIENT]; /**< Array of interface manager client details*/ } __rte_cache_aligned interface_main_t; /** * Init function of Interface manager. Calls port_setup function for every port. * * @param *pconfig * A pointer to port_config_t contains port configuration. * * @returns * IFM_SUCCESS - On success. * IFM_FAILURE - On Failure. */ int ifm_configure_ports(port_config_t *pconfig); /** * Returns first port from port list. * * @param * None * * @returns * On success - Returns a pointer to first port in the list of * type l2_phy_interface_t. * NULL - On Failure. */ l2_phy_interface_t *ifm_get_first_port(void); /** * Get a port from the physical port list which is next node to * the given portid in the list. * * @param portid * A pmdid of port. * * @returns * On success - Returns a pointer to next port in the list of * type l2_phy_interface_t. * NULL - On Failure. */ l2_phy_interface_t *ifm_get_next_port(uint8_t port_id); /** * Get a pointer to port for the given portid from the physical port list. * * @param portid * A pmd id of the port. * * @returns * On success - returns pointer to l2_phy_interface_t. * NULL - On Failure. */ l2_phy_interface_t *ifm_get_port(uint8_t); /** * Get a pointer to port for the given port name from the physical port list. * * @param name * Name of the port * * @returns * On success - returns pointer to l2_phy_interface_t. * NULL - On Failure. */ l2_phy_interface_t *ifm_get_port_by_name(const char *name); /** * Removes given port from the physical interface list. * * @params * portid - pmd_id of port. * @returns * none */ void ifm_remove_port_details(uint8_t portid); /** * Adds give port to the begining of physical interface list. * * @param l2_phy_interface_t * * pointer to l2_phy_interface_t. * @returns * none */ void ifm_add_port_to_port_list(l2_phy_interface_t *); /** * Checks whether the global physical port list is NULL. * * @returns * 0 - On success. * 1 - On Failure. */ int is_port_list_null(void); /** * Configures the device port. Also sets tx and rx queue. * Populates port structure and adds it physical interface list. * * @param portconfig * Contains configuration about rx queue, tx queue. * * @returns * IFM_SUCCESS - On success. * IFM_FAILURE - On Failure. */ int ifm_port_setup(uint8_t port_id, port_config_t *); /** * Initializes interface manager main structure * @params * none * @returns * none */ void ifm_init(void); /** * Returns number of ports initialized during pci probe. * * @params * void * * @returns * number of ports initialized - On success. * IFM_FAILURE - On Failure. */ int32_t ifm_get_nports_initialized(void); /** * Returns number of ports initialized ifm_init. * * @params * void * * @returns * number of ports initialized - On success. * IFM_FAILURE - On Failure. */ int32_t ifm_get_nactive_ports(void); /** * Checks whether port is ipv4 enabled. * * @param portid * A pmd id of the port. * * @returns * IFM_SUCCESS - On success. * IFM_FAILURE - On Failure. */ int32_t ifm_chk_port_ipv4_enabled(uint8_t port_id); /** * Checks whether port is ipv6 enabled. * * @param portid * A pmd id of the port. * * @returns * IFM_SUCCESS - On success. * IFM_FAILURE - On Failure. */ int32_t ifm_chk_port_ipv6_enabled(uint8_t port_id); /** * Remove ipv4 address from the given port. * * @param portid * A pmd id of the port. * @param ipaddr * ipv4 address to be removed * @param addrlen * ipv4 address length * * @returns * IFM_SUCCESS - On success. * IFM_FAILURE - On Failure. */ int16_t ifm_remove_ipv4_port(uint8_t port_id, uint32_t ipaddr, uint32_t addrlen); /** * Remove ipv6 address from the given port. * * @param portid * A pmd id of the port. * @param ip6addr * ipv4 address to be removed * @param addrlen * ipv4 address length * * @returns * IFM_SUCCESS - On success. * IFM_FAILURE - On Failure. */ int16_t ifm_remove_ipv6_port(uint8_t port_id, uint32_t ip6addr, uint32_t addrlen); /** * Add ipv4 address to the given port. * * @param portid * A pmd id of the port. * @param ipaddr * ipv4 address to be configured * @param addrlen * ipv4 address length * * @returns * IFM_SUCCESS - On success. * IFM_FAILURE - On Failure. */ int16_t ifm_add_ipv4_port(uint8_t port_id, uint32_t ipaddr, uint32_t addrlen); /** * Add ipv6 address to the given port. * * @param portid * A pmd id of the port. * @param ip6addr * ipv6 address to be configured * @param addrlen * ipv4 address length * * @returns * IFM_SUCCESS - On success. * IFM_FAILURE - On Failure. */ int8_t ifm_add_ipv6_port(uint8_t port_id, uint8_t ip6addr[], uint32_t addrlen); /** * Buffers the packet in the tx quueue. * * @param *port * pointer to the port. * @param *tx_pkts * packet to be transmitted * * @returns * number of packets transmitted */ int ifm_transmit_single_pkt(l2_phy_interface_t *port, struct rte_mbuf *tx_pkts); /** * Transmit the packet * * @param *port * pointer to the port. * @param *tx_pkts * packets to be transmitted * @param npkts * number of packets to be transmitted * * @returns * number of packets transmitted */ uint16_t ifm_transmit_bulk_pkts(l2_phy_interface_t *, struct rte_mbuf **tx_pkts, uint64_t npkts); /** * Receive burst of 32 packets * * @param portid * From which port we need to read packets * @param qid * From which port we need to read packets * @param npkts * mbuf in which read packets will be placed * * @returns * number of packets read */ uint16_t ifm_receive_bulk_pkts(uint8_t port_id, uint16_t qid, struct rte_mbuf **rx_pkts); /** * Enable or disable promiscmous mode * * @param portid * pmd id of the port * @param enable * 1 - enable, IFM_SUCCESS - disable * * @returns * none */ void ifm_set_port_promisc(uint8_t port_id, uint8_t enable); /** * Enable or disable promiscmous mode * * @param portid * pmd id of the port * @param enable * 1 - enable, 0 - disable * * @returns * none */ void ifm_set_l2_interface_mtu(uint8_t port_id, uint16_t mtu); /** * Set MTU value for the port * * @param portid * pmd id of the port * @param mtu * MTU value * * @returns * none */ void ifm_update_linkstatus(uint8_t port_id, uint16_t linkstatus); /** * Register for link state event * * @param clientid * Unique number identifies client. * @param cb_linkupdate * Callback function which has to be called at time of event * * @returns * none */ void ifm_register_for_linkupdate(uint32_t clientid, void (*cb_linkupdate) (uint8_t, unsigned int)); /** * Callback which is triggered at the time of link state change which in turn triggers registered * clients callback * * @param portid * pmd id of the port * @param type * lsi event type * @param * Currently not used * * @returns * none */ void lsi_event_callback(uint8_t port_id, enum rte_eth_event_type type, void *param); /* * Prints list of interfaces * @param vois */ void print_interface_details(void); /* * Creates bond interface * @Param name * name of bond port * @Param mode * mode * @Param portconf * port configuration to be applied * @returns 0 on success and 1 on failure */ int ifm_bond_port_create(const char *name, int mode, port_config_t *portconf); /* * Deletes bond interface * @Param name * name of bond port * @returns 0 on success and 1 on failure */ int ifm_bond_port_delete(const char *name); /* * Addes a port as slave to bond * @Param bonded_port_id * bond port id * @Param slave_port_id * slave port s port id * @returns 0 on success and 1 on failure */ int ifm_add_slave_port(uint8_t bonded_port_id, uint8_t slave_port_id); /* * Removes a port as slave to bond * @Param bonded_port_id * bond port id * @Param slave_port_id * slave port s port id * @returns 0 on success and 1 on failure */ int ifm_remove_slave_port(uint8_t bonded_port_id, uint8_t slave_port_id); /* * Sets bond port 's mode * @Param bonded_port_id * bond port id * @Param mode * mode 0 ... 5 * @returns 0 on success and 1 on failure */ int set_bond_mode(uint8_t bonded_port_id, uint8_t mode); /* * Get bond port 's mode * @Param bonded_port_id * bond port id * @returns mode value or -1 on failure */ int get_bond_mode(uint8_t bonded_port_id); /* * Set a slave port to bond * @Param bonded_port_id * bond port id * @Param slave_port_id * slave port s port id * @returns 0 on success and 1 on failure */ int set_bond_primary(uint8_t bonded_port_id, uint8_t slave_port_id); /* * Get primary port of the bond * @Param bonded_port_id * bond port id * @returns port id of primary on success and 1 on failure */ int get_bond_primary_port(uint8_t bonded_port_id); /* * Get slave count for the bond * @Param bonded_port_id * bond port id * @returns slave count on success and 1 on failure */ int get_bond_slave_count(uint8_t bonded_port_id); /* * Get active slave count for the bond * @Param bonded_port_id * bond port id * @returns active slaves count on success and 1 on failure */ int get_bond_active_slave_count(uint8_t bonded_port_id); /* * Get slaves in the bond * @Param bonded_port_id * bond port id * @Param slaves * array to save slave port * @returns 0 on success and 1 on failure */ int get_bond_slaves(uint8_t bonded_port_id, uint8_t slaves[RTE_MAX_ETHPORTS]); /* * Get active slaves in the bond * @Param bonded_port_id * bond port id * @Param slaves * array to save slave port * @returns 0 on success and 1 on failure */ int get_bond_active_slaves(uint8_t bonded_port_id, uint8_t slaves[RTE_MAX_ETHPORTS]); /* * Sets bond port 's mac address * @Param bonded_port_id * bond port id * @Param mode * mac_addr - mac addr * @returns 0 on success and 1 on failure */ int set_bond_mac_address(uint8_t bonded_port_id, struct ether_addr *mac_addr); /* * Sets bond port 's MAC * @Param bonded_port_id * bond port id * @returns 0 on success and 1 on failure */ int reset_bond_mac_addr(uint8_t bonded_port_id); int get_bond_mac(uint8_t bonded_port_id, struct ether_addr *macaddr); /* * Sets bond port 's policy * @Param bonded_port_id * bond port id * @Param policy * xmit policy * @returns 0 on success and 1 on failure */ int set_bond_xmitpolicy(uint8_t bonded_port_id, uint8_t policy); /* * Get bond port 's xmit policy * @Param bonded_port_id * bond port id * @returns xmit policy value or -1 on failure */ int get_bond_xmitpolicy(uint8_t bonded_port_id); /* * Sets bond port 's monitor frequency * @Param bonded_port_id * bond port id * @Param internal_ms * frequency in ms * @returns 0 on success and 1 on failure */ int set_bond_link_montitor_frequency(uint8_t bonded_port_id, uint32_t internal_ms); /* * Get bond port 's monitor frequency * @Param bonded_port_id * bond port id * @returns frequency value or -1 on failure */ int get_bond_link_monitor_frequency(uint8_t bonded_port_id); /* * Sets bond port 's link down delay * @Param bonded_port_id * bond port id * @Param delay_ms * delay time in ms * @returns 0 on success and 1 on failure */ int set_bond_linkdown_delay(uint8_t bonded_port_id, uint32_t delay_ms); /* * Get bond port 's link down delay * @Param bonded_port_id * bond port id * @returns delay ms value or -1 on failure */ int get_bond_link_down_delay(uint8_t bonded_port_id); /* * Sets bond port 's link up delay * @Param bonded_port_id * bond port id * @Param delay_ms * delay time in ms * @returns 0 on success and 1 on failure */ int set_bond_linkup_delay(uint8_t bonded_port_id, uint32_t delay_ms); /* * Get bond port 's link up delay * @Param bonded_port_id * bond port id * @returns delay ms value or -1 on failure */ int get_bond_link_up_delay(uint8_t bonded_port_id); /* * Print port s statistics * @Param void * @returns void */ void print_stats(void); /* * Gets information about port * @Param port_id * portid of the port * @param port_info * port to address to copy port info * @returns 0 on success otherwise -1 */ int ifm_get_port_info(uint8_t port_id, l2_phy_interface_t *port_info); /* * Gets information about next port of given portid * @Param port_id * portid of the port * @param port_info * port to address to copy port info * @returns 0 on success otherwise -1 */ int ifm_get_next_port_info(uint8_t port_id, l2_phy_interface_t *port_info); /* * Enable ifm debug * @Param dbg value * Debug- 1(port config),2(port RXTX),3(hle LOCKS),4(GENERALDEBUG) * @param flag * Enable 1, disable 0 * @returns 0 on success otherwise -1 */ void config_ifm_debug(int dbg, int flag); #endif