Esempio n. 1
0
struct metadata_dst *iptunnel_metadata_reply(struct metadata_dst *md,
					     gfp_t flags)
{
	struct metadata_dst *res;
	struct ip_tunnel_info *dst, *src;

	if (!md || md->u.tun_info.mode & IP_TUNNEL_INFO_TX)
		return NULL;

	res = metadata_dst_alloc(0, flags);
	if (!res)
		return NULL;

	dst = &res->u.tun_info;
	src = &md->u.tun_info;
	dst->key.tun_id = src->key.tun_id;
	if (src->mode & IP_TUNNEL_INFO_IPV6)
		memcpy(&dst->key.u.ipv6.dst, &src->key.u.ipv6.src,
		       sizeof(struct in6_addr));
	else
		dst->key.u.ipv4.dst = src->key.u.ipv4.src;
	dst->mode = src->mode | IP_TUNNEL_INFO_TX;

	return res;
}
Esempio n. 2
0
static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi)
{
	struct net *net = dev_net(skb->dev);
	struct metadata_dst *tun_dst = NULL;
	struct ip_tunnel_net *itn;
	const struct iphdr *iph;
	struct ip_tunnel *tunnel;

	if (tpi->proto == htons(ETH_P_TEB))
		itn = net_generic(net, gre_tap_net_id);
	else
		itn = net_generic(net, ipgre_net_id);

	iph = ip_hdr(skb);
	tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags,
				  iph->saddr, iph->daddr, tpi->key);

	if (tunnel) {
		skb_pop_mac_header(skb);
		if (tunnel->collect_md) {
			struct ip_tunnel_info *info;

			tun_dst = metadata_dst_alloc(0, GFP_ATOMIC);
			if (!tun_dst)
				return PACKET_REJECT;

			info = &tun_dst->u.tun_info;
			info->key.ipv4_src = iph->saddr;
			info->key.ipv4_dst = iph->daddr;
			info->key.ipv4_tos = iph->tos;
			info->key.ipv4_ttl = iph->ttl;

			info->mode = IP_TUNNEL_INFO_RX;
			info->key.tun_flags = tpi->flags &
					      (TUNNEL_CSUM | TUNNEL_KEY);
			info->key.tun_id = key_to_tunnel_id(tpi->key);

			info->key.tp_src = 0;
			info->key.tp_dst = 0;
		}

		ip_tunnel_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error);
		return PACKET_RCVD;
	}
	return PACKET_REJECT;
}
Esempio n. 3
0
int nfp_repr_init(struct nfp_app *app, struct net_device *netdev,
		  u32 cmsg_port_id, struct nfp_port *port,
		  struct net_device *pf_netdev)
{
	struct nfp_repr *repr = netdev_priv(netdev);
	struct nfp_net *nn = netdev_priv(pf_netdev);
	u32 repr_cap = nn->tlv_caps.repr_cap;
	int err;

	nfp_repr_set_lockdep_class(netdev);

	repr->port = port;
	repr->dst = metadata_dst_alloc(0, METADATA_HW_PORT_MUX, GFP_KERNEL);
	if (!repr->dst)
		return -ENOMEM;
	repr->dst->u.port_info.port_id = cmsg_port_id;
	repr->dst->u.port_info.lower_dev = pf_netdev;

	netdev->netdev_ops = &nfp_repr_netdev_ops;
	netdev->ethtool_ops = &nfp_port_ethtool_ops;

	netdev->max_mtu = pf_netdev->max_mtu;

	/* Set features the lower device can support with representors */
	if (repr_cap & NFP_NET_CFG_CTRL_LIVE_ADDR)
		netdev->priv_flags |= IFF_LIVE_ADDR_CHANGE;

	netdev->hw_features = NETIF_F_HIGHDMA;
	if (repr_cap & NFP_NET_CFG_CTRL_RXCSUM_ANY)
		netdev->hw_features |= NETIF_F_RXCSUM;
	if (repr_cap & NFP_NET_CFG_CTRL_TXCSUM)
		netdev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
	if (repr_cap & NFP_NET_CFG_CTRL_GATHER)
		netdev->hw_features |= NETIF_F_SG;
	if ((repr_cap & NFP_NET_CFG_CTRL_LSO && nn->fw_ver.major > 2) ||
	    repr_cap & NFP_NET_CFG_CTRL_LSO2)
		netdev->hw_features |= NETIF_F_TSO | NETIF_F_TSO6;
	if (repr_cap & NFP_NET_CFG_CTRL_RSS_ANY)
		netdev->hw_features |= NETIF_F_RXHASH;
	if (repr_cap & NFP_NET_CFG_CTRL_VXLAN) {
		if (repr_cap & NFP_NET_CFG_CTRL_LSO)
			netdev->hw_features |= NETIF_F_GSO_UDP_TUNNEL;
	}
	if (repr_cap & NFP_NET_CFG_CTRL_NVGRE) {
		if (repr_cap & NFP_NET_CFG_CTRL_LSO)
			netdev->hw_features |= NETIF_F_GSO_GRE;
	}
	if (repr_cap & (NFP_NET_CFG_CTRL_VXLAN | NFP_NET_CFG_CTRL_NVGRE))
		netdev->hw_enc_features = netdev->hw_features;

	netdev->vlan_features = netdev->hw_features;

	if (repr_cap & NFP_NET_CFG_CTRL_RXVLAN)
		netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_RX;
	if (repr_cap & NFP_NET_CFG_CTRL_TXVLAN) {
		if (repr_cap & NFP_NET_CFG_CTRL_LSO2)
			netdev_warn(netdev, "Device advertises both TSO2 and TXVLAN. Refusing to enable TXVLAN.\n");
		else
			netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_TX;
	}
	if (repr_cap & NFP_NET_CFG_CTRL_CTAG_FILTER)
		netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER;

	netdev->features = netdev->hw_features;

	/* Advertise but disable TSO by default. */
	netdev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6);
	netdev->gso_max_segs = NFP_NET_LSO_MAX_SEGS;

	netdev->priv_flags |= IFF_NO_QUEUE | IFF_DISABLE_NETPOLL;
	netdev->features |= NETIF_F_LLTX;

	if (nfp_app_has_tc(app)) {
		netdev->features |= NETIF_F_HW_TC;
		netdev->hw_features |= NETIF_F_HW_TC;
	}

	err = nfp_app_repr_init(app, netdev);
	if (err)
		goto err_clean;

	err = register_netdev(netdev);
	if (err)
		goto err_repr_clean;

	return 0;

err_repr_clean:
	nfp_app_repr_clean(app, netdev);
err_clean:
	dst_release((struct dst_entry *)repr->dst);
	return err;
}