vf representor

# devlink dev eswitch set pci/0000:05:00.0 mode switchdev
# echo 2 > /sys/class/net/enp5s0f0/device/sriov_numvfs
# ip l show
297: enp5s0f0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop portid 6805ca2e7268 state DOWN mode DEFAULT group default qlen 1000
     link/ether 68:05:ca:2e:72:68 brd ff:ff:ff:ff:ff:ff
     vf 0 MAC 00:00:00:00:00:00, spoof checking on, link-state auto, trust off
     vf 1 MAC 00:00:00:00:00:00, spoof checking on, link-state auto, trust off
299: enp5s0f0-vf0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
     link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff
300: enp5s0f0-vf1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
     link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff

 static int i40e_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode)
 {
    struct i40e_pf *pf = devlink_priv(devlink);
    int err = 0;
    struct i40e_vf *vf;
    int i, j, err = 0;

    if (mode == pf->eswitch_mode)
        goto done;

    switch (mode) {
    case DEVLINK_ESWITCH_MODE_LEGACY:
        for (i = 0; i < pf->num_alloc_vfs; i++) {
            vf = &(pf->vf[i]);
            i40e_free_vfpr_netdev(vf);
        }
        pf->eswitch_mode = mode;
        break;
    case DEVLINK_ESWITCH_MODE_SWITCHDEV:
        for (i = 0; i < pf->num_alloc_vfs; i++) {
            vf = &(pf->vf[i]);
            err = i40e_alloc_vfpr_netdev(vf, i);
            if (err) {
                for (j = 0; j < i; j++) {
                    vf = &(pf->vf[j]);
                    i40e_free_vfpr_netdev(vf);
                }
                goto done;
            }
        }
                pf->eswitch_mode = mode;
        break;
    }
     
int i40e_alloc_vfpr_netdev(struct i40e_vf *vf, u16 vf_num)
{
    struct net_device *vfpr_netdev;
    char netdev_name[IFNAMSIZ];
    struct i40e_vfpr_netdev_priv *priv;
    struct i40e_pf *pf = vf->pf;
    struct i40e_vsi *vsi = pf->vsi[pf->lan_vsi];
    int err;

    snprintf(netdev_name, IFNAMSIZ, "%s-vf%d", vsi->netdev->name, vf_num);
    vfpr_netdev = alloc_netdev(sizeof(struct i40e_vfpr_netdev_priv),
                   netdev_name, NET_NAME_UNKNOWN, ether_setup);
    if (!vfpr_netdev) {
        dev_err(&pf->pdev->dev, "alloc_netdev failed for vf:%d
",
            vf_num);
        return -ENOMEM;
    }

    pf->vf[vf_num].vfpr_netdev = vfpr_netdev;

    priv = netdev_priv(vfpr_netdev);
    priv->vf = &(pf->vf[vf_num]);

    vfpr_netdev->netdev_ops = &i40e_vfpr_netdev_ops;

    netif_carrier_off(vfpr_netdev);
    netif_tx_disable(vfpr_netdev);

    err = register_netdev(vfpr_netdev);
    if (err) {
        dev_err(&pf->pdev->dev, "register_netdev failed for vf: %s
",
            vf->vfpr_netdev->name);
        free_netdev(vfpr_netdev);
        return err;
    }

    dev_info(&pf->pdev->dev, "VF Port representor(%s) created for VF %d
",
         vf->vfpr_netdev->name, vf_num);

    /* Delete broadcast filter for VF */
    i40e_update_vf_broadcast_filter(vf, false);

    return 0;
}
struct mlx5_eswitch_rep_ops {
    int (*load)(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep);
    void (*unload)(struct mlx5_eswitch_rep *rep);
    void *(*get_proto_dev)(struct mlx5_eswitch_rep *rep);
};

struct mlx5_eswitch_rep_data {
    void *priv;
    atomic_t state;
};

struct mlx5_eswitch_rep {
    struct mlx5_eswitch_rep_data rep_data[NUM_REP_TYPES];
    u16               vport;
    u16               vlan;
    /* Only IB rep is using vport_index */
    u16               vport_index;
    u32               vlan_refcount;
};


static void *mlx5e_vport_rep_get_proto_dev(struct mlx5_eswitch_rep *rep)
{
        struct mlx5e_rep_priv *rpriv;

        rpriv = mlx5e_rep_to_rep_priv(rep);

        return rpriv->netdev;
}

static inline
struct mlx5e_rep_priv *mlx5e_rep_to_rep_priv(struct mlx5_eswitch_rep *rep)
{
        return rep->rep_data[REP_ETH].priv;
}


/* e-Switch vport representors */
static int
mlx5e_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
{
        const struct mlx5e_profile *profile;
        struct mlx5e_rep_priv *rpriv;
        struct net_device *netdev;
        int nch, err;

        rpriv = kzalloc(sizeof(*rpriv), GFP_KERNEL);
        if (!rpriv)
                return -ENOMEM;

        /* rpriv->rep to be looked up when profile->init() is called */
        rpriv->rep = rep;

        nch = mlx5e_get_max_num_channels(dev);
        profile = (rep->vport == MLX5_VPORT_UPLINK) ?
                  &mlx5e_uplink_rep_profile : &mlx5e_rep_profile;
        netdev = mlx5e_create_netdev(dev, profile, nch, rpriv);
        
        rpriv->netdev = netdev;
        rep->rep_data[REP_ETH].priv = rpriv;
        INIT_LIST_HEAD(&rpriv->vport_sqs_list);

        if (rep->vport == MLX5_VPORT_UPLINK) {
                err = mlx5e_create_mdev_resources(dev);
                if (err)
                        goto err_destroy_netdev;
        }

        err = mlx5e_attach_netdev(netdev_priv(netdev));
     

        err = mlx5e_rep_neigh_init(rpriv);
       

        err = register_devlink_port(dev, rpriv);
 

        err = register_netdev(netdev);
}
原文地址:https://www.cnblogs.com/dream397/p/14479392.html