Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright(c) 2017 Intel Corporation.
0003  *
0004  * This file is provided under a dual BSD/GPLv2 license.  When using or
0005  * redistributing this file, you may do so under either license.
0006  *
0007  * GPL LICENSE SUMMARY
0008  *
0009  * This program is free software; you can redistribute it and/or modify
0010  * it under the terms of version 2 of the GNU General Public License as
0011  * published by the Free Software Foundation.
0012  *
0013  * This program is distributed in the hope that it will be useful, but
0014  * WITHOUT ANY WARRANTY; without even the implied warranty of
0015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0016  * General Public License for more details.
0017  *
0018  * BSD LICENSE
0019  *
0020  * Redistribution and use in source and binary forms, with or without
0021  * modification, are permitted provided that the following conditions
0022  * are met:
0023  *
0024  *  - Redistributions of source code must retain the above copyright
0025  *    notice, this list of conditions and the following disclaimer.
0026  *  - Redistributions in binary form must reproduce the above copyright
0027  *    notice, this list of conditions and the following disclaimer in
0028  *    the documentation and/or other materials provided with the
0029  *    distribution.
0030  *  - Neither the name of Intel Corporation nor the names of its
0031  *    contributors may be used to endorse or promote products derived
0032  *    from this software without specific prior written permission.
0033  *
0034  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
0035  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
0036  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
0037  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
0038  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0039  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0040  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
0041  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
0042  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0043  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
0044  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0045  *
0046  */
0047 
0048 /*
0049  * This file contains OPA Virtual Network Interface Controller (VNIC) driver
0050  * netdev functionality.
0051  */
0052 
0053 #include <linux/if_vlan.h>
0054 #include <linux/crc32.h>
0055 
0056 #include "opa_vnic_internal.h"
0057 
0058 #define OPA_TX_TIMEOUT_MS 1000
0059 
0060 #define OPA_VNIC_SKB_HEADROOM  \
0061             ALIGN((OPA_VNIC_HDR_LEN + OPA_VNIC_SKB_MDATA_LEN), 8)
0062 
0063 /* This function is overloaded for opa_vnic specific implementation */
0064 static void opa_vnic_get_stats64(struct net_device *netdev,
0065                  struct rtnl_link_stats64 *stats)
0066 {
0067     struct opa_vnic_adapter *adapter = opa_vnic_priv(netdev);
0068     struct opa_vnic_stats vstats;
0069 
0070     memset(&vstats, 0, sizeof(vstats));
0071     spin_lock(&adapter->stats_lock);
0072     adapter->rn_ops->ndo_get_stats64(netdev, &vstats.netstats);
0073     spin_unlock(&adapter->stats_lock);
0074     memcpy(stats, &vstats.netstats, sizeof(*stats));
0075 }
0076 
0077 /* opa_netdev_start_xmit - transmit function */
0078 static netdev_tx_t opa_netdev_start_xmit(struct sk_buff *skb,
0079                      struct net_device *netdev)
0080 {
0081     struct opa_vnic_adapter *adapter = opa_vnic_priv(netdev);
0082 
0083     v_dbg("xmit: queue %d skb len %d\n", skb->queue_mapping, skb->len);
0084     /* pad to ensure mininum ethernet packet length */
0085     if (unlikely(skb->len < ETH_ZLEN)) {
0086         if (skb_padto(skb, ETH_ZLEN))
0087             return NETDEV_TX_OK;
0088 
0089         skb_put(skb, ETH_ZLEN - skb->len);
0090     }
0091 
0092     opa_vnic_encap_skb(adapter, skb);
0093     return adapter->rn_ops->ndo_start_xmit(skb, netdev);
0094 }
0095 
0096 static u16 opa_vnic_select_queue(struct net_device *netdev, struct sk_buff *skb,
0097                  struct net_device *sb_dev)
0098 {
0099     struct opa_vnic_adapter *adapter = opa_vnic_priv(netdev);
0100     struct opa_vnic_skb_mdata *mdata;
0101     int rc;
0102 
0103     /* pass entropy and vl as metadata in skb */
0104     mdata = skb_push(skb, sizeof(*mdata));
0105     mdata->entropy = opa_vnic_calc_entropy(skb);
0106     mdata->vl = opa_vnic_get_vl(adapter, skb);
0107     rc = adapter->rn_ops->ndo_select_queue(netdev, skb, sb_dev);
0108     skb_pull(skb, sizeof(*mdata));
0109     return rc;
0110 }
0111 
0112 static void opa_vnic_update_state(struct opa_vnic_adapter *adapter, bool up)
0113 {
0114     struct __opa_veswport_info *info = &adapter->info;
0115 
0116     mutex_lock(&adapter->lock);
0117     /* Operational state can only be DROP_ALL or FORWARDING */
0118     if ((info->vport.config_state == OPA_VNIC_STATE_FORWARDING) && up) {
0119         info->vport.oper_state = OPA_VNIC_STATE_FORWARDING;
0120         info->vport.eth_link_status = OPA_VNIC_ETH_LINK_UP;
0121     } else {
0122         info->vport.oper_state = OPA_VNIC_STATE_DROP_ALL;
0123         info->vport.eth_link_status = OPA_VNIC_ETH_LINK_DOWN;
0124     }
0125 
0126     if (info->vport.config_state == OPA_VNIC_STATE_FORWARDING)
0127         netif_dormant_off(adapter->netdev);
0128     else
0129         netif_dormant_on(adapter->netdev);
0130     mutex_unlock(&adapter->lock);
0131 }
0132 
0133 /* opa_vnic_process_vema_config - process vema configuration updates */
0134 void opa_vnic_process_vema_config(struct opa_vnic_adapter *adapter)
0135 {
0136     struct __opa_veswport_info *info = &adapter->info;
0137     struct rdma_netdev *rn = netdev_priv(adapter->netdev);
0138     u8 port_num[OPA_VESW_MAX_NUM_DEF_PORT] = { 0 };
0139     struct net_device *netdev = adapter->netdev;
0140     u8 i, port_count = 0;
0141     u16 port_mask;
0142 
0143     /* If the base_mac_addr is changed, update the interface mac address */
0144     if (memcmp(info->vport.base_mac_addr, adapter->vema_mac_addr,
0145            ARRAY_SIZE(info->vport.base_mac_addr))) {
0146         struct sockaddr saddr;
0147 
0148         memcpy(saddr.sa_data, info->vport.base_mac_addr,
0149                ARRAY_SIZE(info->vport.base_mac_addr));
0150         mutex_lock(&adapter->lock);
0151         eth_commit_mac_addr_change(netdev, &saddr);
0152         memcpy(adapter->vema_mac_addr,
0153                info->vport.base_mac_addr, ETH_ALEN);
0154         mutex_unlock(&adapter->lock);
0155     }
0156 
0157     rn->set_id(netdev, info->vesw.vesw_id);
0158 
0159     /* Handle MTU limit change */
0160     rtnl_lock();
0161     netdev->max_mtu = max_t(unsigned int, info->vesw.eth_mtu,
0162                 netdev->min_mtu);
0163     if (netdev->mtu > netdev->max_mtu)
0164         dev_set_mtu(netdev, netdev->max_mtu);
0165     rtnl_unlock();
0166 
0167     /* Update flow to default port redirection table */
0168     port_mask = info->vesw.def_port_mask;
0169     for (i = 0; i < OPA_VESW_MAX_NUM_DEF_PORT; i++) {
0170         if (port_mask & 1)
0171             port_num[port_count++] = i;
0172         port_mask >>= 1;
0173     }
0174 
0175     /*
0176      * Build the flow table. Flow table is required when destination LID
0177      * is not available. Up to OPA_VNIC_FLOW_TBL_SIZE flows supported.
0178      * Each flow need a default port number to get its dlid from the
0179      * u_ucast_dlid array.
0180      */
0181     for (i = 0; i < OPA_VNIC_FLOW_TBL_SIZE; i++)
0182         adapter->flow_tbl[i] = port_count ? port_num[i % port_count] :
0183                             OPA_VNIC_INVALID_PORT;
0184 
0185     /* update state */
0186     opa_vnic_update_state(adapter, !!(netdev->flags & IFF_UP));
0187 }
0188 
0189 /*
0190  * Set the power on default values in adapter's vema interface structure.
0191  */
0192 static inline void opa_vnic_set_pod_values(struct opa_vnic_adapter *adapter)
0193 {
0194     adapter->info.vport.max_mac_tbl_ent = OPA_VNIC_MAC_TBL_MAX_ENTRIES;
0195     adapter->info.vport.max_smac_ent = OPA_VNIC_MAX_SMAC_LIMIT;
0196     adapter->info.vport.config_state = OPA_VNIC_STATE_DROP_ALL;
0197     adapter->info.vport.eth_link_status = OPA_VNIC_ETH_LINK_DOWN;
0198     adapter->info.vesw.eth_mtu = ETH_DATA_LEN;
0199 }
0200 
0201 /* opa_vnic_set_mac_addr - change mac address */
0202 static int opa_vnic_set_mac_addr(struct net_device *netdev, void *addr)
0203 {
0204     struct opa_vnic_adapter *adapter = opa_vnic_priv(netdev);
0205     struct sockaddr *sa = addr;
0206     int rc;
0207 
0208     if (!memcmp(netdev->dev_addr, sa->sa_data, ETH_ALEN))
0209         return 0;
0210 
0211     mutex_lock(&adapter->lock);
0212     rc = eth_mac_addr(netdev, addr);
0213     mutex_unlock(&adapter->lock);
0214     if (rc)
0215         return rc;
0216 
0217     adapter->info.vport.uc_macs_gen_count++;
0218     opa_vnic_vema_report_event(adapter,
0219                    OPA_VESWPORT_TRAP_IFACE_UCAST_MAC_CHANGE);
0220     return 0;
0221 }
0222 
0223 /*
0224  * opa_vnic_mac_send_event - post event on possible mac list exchange
0225  *  Send trap when digest from uc/mc mac list differs from previous run.
0226  *  Digest is evaluated similar to how cksum does.
0227  */
0228 static void opa_vnic_mac_send_event(struct net_device *netdev, u8 event)
0229 {
0230     struct opa_vnic_adapter *adapter = opa_vnic_priv(netdev);
0231     struct netdev_hw_addr *ha;
0232     struct netdev_hw_addr_list *hw_list;
0233     u32 *ref_crc;
0234     u32 l, crc = 0;
0235 
0236     switch (event) {
0237     case OPA_VESWPORT_TRAP_IFACE_UCAST_MAC_CHANGE:
0238         hw_list = &netdev->uc;
0239         adapter->info.vport.uc_macs_gen_count++;
0240         ref_crc = &adapter->umac_hash;
0241         break;
0242     case OPA_VESWPORT_TRAP_IFACE_MCAST_MAC_CHANGE:
0243         hw_list = &netdev->mc;
0244         adapter->info.vport.mc_macs_gen_count++;
0245         ref_crc = &adapter->mmac_hash;
0246         break;
0247     default:
0248         return;
0249     }
0250     netdev_hw_addr_list_for_each(ha, hw_list) {
0251         crc = crc32_le(crc, ha->addr, ETH_ALEN);
0252     }
0253     l = netdev_hw_addr_list_count(hw_list) * ETH_ALEN;
0254     crc = ~crc32_le(crc, (void *)&l, sizeof(l));
0255 
0256     if (crc != *ref_crc) {
0257         *ref_crc = crc;
0258         opa_vnic_vema_report_event(adapter, event);
0259     }
0260 }
0261 
0262 /* opa_vnic_set_rx_mode - handle uc/mc mac list change */
0263 static void opa_vnic_set_rx_mode(struct net_device *netdev)
0264 {
0265     opa_vnic_mac_send_event(netdev,
0266                 OPA_VESWPORT_TRAP_IFACE_UCAST_MAC_CHANGE);
0267 
0268     opa_vnic_mac_send_event(netdev,
0269                 OPA_VESWPORT_TRAP_IFACE_MCAST_MAC_CHANGE);
0270 }
0271 
0272 /* opa_netdev_open - activate network interface */
0273 static int opa_netdev_open(struct net_device *netdev)
0274 {
0275     struct opa_vnic_adapter *adapter = opa_vnic_priv(netdev);
0276     int rc;
0277 
0278     rc = adapter->rn_ops->ndo_open(adapter->netdev);
0279     if (rc) {
0280         v_dbg("open failed %d\n", rc);
0281         return rc;
0282     }
0283 
0284     /* Update status and send trap */
0285     opa_vnic_update_state(adapter, true);
0286     opa_vnic_vema_report_event(adapter,
0287                    OPA_VESWPORT_TRAP_ETH_LINK_STATUS_CHANGE);
0288     return 0;
0289 }
0290 
0291 /* opa_netdev_close - disable network interface */
0292 static int opa_netdev_close(struct net_device *netdev)
0293 {
0294     struct opa_vnic_adapter *adapter = opa_vnic_priv(netdev);
0295     int rc;
0296 
0297     rc = adapter->rn_ops->ndo_stop(adapter->netdev);
0298     if (rc) {
0299         v_dbg("close failed %d\n", rc);
0300         return rc;
0301     }
0302 
0303     /* Update status and send trap */
0304     opa_vnic_update_state(adapter, false);
0305     opa_vnic_vema_report_event(adapter,
0306                    OPA_VESWPORT_TRAP_ETH_LINK_STATUS_CHANGE);
0307     return 0;
0308 }
0309 
0310 /* netdev ops */
0311 static const struct net_device_ops opa_netdev_ops = {
0312     .ndo_open = opa_netdev_open,
0313     .ndo_stop = opa_netdev_close,
0314     .ndo_start_xmit = opa_netdev_start_xmit,
0315     .ndo_get_stats64 = opa_vnic_get_stats64,
0316     .ndo_set_rx_mode = opa_vnic_set_rx_mode,
0317     .ndo_select_queue = opa_vnic_select_queue,
0318     .ndo_set_mac_address = opa_vnic_set_mac_addr,
0319 };
0320 
0321 /* opa_vnic_add_netdev - create vnic netdev interface */
0322 struct opa_vnic_adapter *opa_vnic_add_netdev(struct ib_device *ibdev,
0323                          u8 port_num, u8 vport_num)
0324 {
0325     struct opa_vnic_adapter *adapter;
0326     struct net_device *netdev;
0327     struct rdma_netdev *rn;
0328     int rc;
0329 
0330     netdev = ibdev->ops.alloc_rdma_netdev(ibdev, port_num,
0331                           RDMA_NETDEV_OPA_VNIC,
0332                           "veth%d", NET_NAME_UNKNOWN,
0333                           ether_setup);
0334     if (!netdev)
0335         return ERR_PTR(-ENOMEM);
0336     else if (IS_ERR(netdev))
0337         return ERR_CAST(netdev);
0338 
0339     rn = netdev_priv(netdev);
0340     adapter = kzalloc(sizeof(*adapter), GFP_KERNEL);
0341     if (!adapter) {
0342         rc = -ENOMEM;
0343         goto adapter_err;
0344     }
0345 
0346     rn->clnt_priv = adapter;
0347     rn->hca = ibdev;
0348     rn->port_num = port_num;
0349     adapter->netdev = netdev;
0350     adapter->ibdev = ibdev;
0351     adapter->port_num = port_num;
0352     adapter->vport_num = vport_num;
0353     adapter->rn_ops = netdev->netdev_ops;
0354 
0355     netdev->netdev_ops = &opa_netdev_ops;
0356     netdev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
0357     netdev->hard_header_len += OPA_VNIC_SKB_HEADROOM;
0358     mutex_init(&adapter->lock);
0359     mutex_init(&adapter->mactbl_lock);
0360     spin_lock_init(&adapter->stats_lock);
0361 
0362     SET_NETDEV_DEV(netdev, ibdev->dev.parent);
0363 
0364     opa_vnic_set_ethtool_ops(netdev);
0365 
0366     opa_vnic_set_pod_values(adapter);
0367 
0368     rc = register_netdev(netdev);
0369     if (rc)
0370         goto netdev_err;
0371 
0372     netif_carrier_off(netdev);
0373     netif_dormant_on(netdev);
0374     v_info("initialized\n");
0375 
0376     return adapter;
0377 netdev_err:
0378     mutex_destroy(&adapter->lock);
0379     mutex_destroy(&adapter->mactbl_lock);
0380     kfree(adapter);
0381 adapter_err:
0382     rn->free_rdma_netdev(netdev);
0383 
0384     return ERR_PTR(rc);
0385 }
0386 
0387 /* opa_vnic_rem_netdev - remove vnic netdev interface */
0388 void opa_vnic_rem_netdev(struct opa_vnic_adapter *adapter)
0389 {
0390     struct net_device *netdev = adapter->netdev;
0391     struct rdma_netdev *rn = netdev_priv(netdev);
0392 
0393     v_info("removing\n");
0394     unregister_netdev(netdev);
0395     opa_vnic_release_mac_tbl(adapter);
0396     mutex_destroy(&adapter->lock);
0397     mutex_destroy(&adapter->mactbl_lock);
0398     kfree(adapter);
0399     rn->free_rdma_netdev(netdev);
0400 }