コード例 #1
0
ファイル: vrf.c プロジェクト: AshishNamdev/linux
/* set dst on skb to send packet to us via dev_xmit path. Allows
 * packet to go through device based features such as qdisc, netfilter
 * hooks and packet sockets with skb->dev set to vrf device.
 */
static struct sk_buff *vrf_ip6_out(struct net_device *vrf_dev,
				   struct sock *sk,
				   struct sk_buff *skb)
{
	struct net_vrf *vrf = netdev_priv(vrf_dev);
	struct dst_entry *dst = NULL;
	struct rt6_info *rt6;

	/* don't divert link scope packets */
	if (rt6_need_strict(&ipv6_hdr(skb)->daddr))
		return skb;

	rcu_read_lock();

	rt6 = rcu_dereference(vrf->rt6);
	if (likely(rt6)) {
		dst = &rt6->dst;
		dst_hold(dst);
	}

	rcu_read_unlock();

	if (unlikely(!dst)) {
		vrf_tx_error(vrf_dev, skb);
		return NULL;
	}

	skb_dst_drop(skb);
	skb_dst_set(skb, dst);

	return skb;
}
コード例 #2
0
ファイル: vrf.c プロジェクト: ReneNyffenegger/linux
static struct sk_buff *vrf_ip6_out(struct net_device *vrf_dev,
				   struct sock *sk,
				   struct sk_buff *skb)
{
	/* don't divert link scope packets */
	if (rt6_need_strict(&ipv6_hdr(skb)->daddr))
		return skb;

	if (qdisc_tx_is_default(vrf_dev))
		return vrf_ip6_out_direct(vrf_dev, sk, skb);

	return vrf_ip6_out_redirect(vrf_dev, skb);
}
コード例 #3
0
ファイル: vrf.c プロジェクト: AshishNamdev/linux
static void vrf_ip6_input_dst(struct sk_buff *skb, struct net_device *vrf_dev,
			      int ifindex)
{
	const struct ipv6hdr *iph = ipv6_hdr(skb);
	struct flowi6 fl6 = {
		.daddr          = iph->daddr,
		.saddr          = iph->saddr,
		.flowlabel      = ip6_flowinfo(iph),
		.flowi6_mark    = skb->mark,
		.flowi6_proto   = iph->nexthdr,
		.flowi6_iif     = ifindex,
	};
	struct net *net = dev_net(vrf_dev);
	struct rt6_info *rt6;

	rt6 = vrf_ip6_route_lookup(net, vrf_dev, &fl6, ifindex,
				   RT6_LOOKUP_F_HAS_SADDR | RT6_LOOKUP_F_IFACE);
	if (unlikely(!rt6))
		return;

	if (unlikely(&rt6->dst == &net->ipv6.ip6_null_entry->dst))
		return;

	skb_dst_set(skb, &rt6->dst);
}

static struct sk_buff *vrf_ip6_rcv(struct net_device *vrf_dev,
				   struct sk_buff *skb)
{
	int orig_iif = skb->skb_iif;
	bool need_strict;

	/* loopback traffic; do not push through packet taps again.
	 * Reset pkt_type for upper layers to process skb
	 */
	if (skb->pkt_type == PACKET_LOOPBACK) {
		skb->dev = vrf_dev;
		skb->skb_iif = vrf_dev->ifindex;
		IP6CB(skb)->flags |= IP6SKB_L3SLAVE;
		skb->pkt_type = PACKET_HOST;
		goto out;
	}

	/* if packet is NDISC or addressed to multicast or link-local
	 * then keep the ingress interface
	 */
	need_strict = rt6_need_strict(&ipv6_hdr(skb)->daddr);
	if (!ipv6_ndisc_frame(skb) && !need_strict) {
		vrf_rx_stats(vrf_dev, skb->len);
		skb->dev = vrf_dev;
		skb->skb_iif = vrf_dev->ifindex;

		skb_push(skb, skb->mac_len);
		dev_queue_xmit_nit(skb, vrf_dev);
		skb_pull(skb, skb->mac_len);

		IP6CB(skb)->flags |= IP6SKB_L3SLAVE;
	}

	if (need_strict)
		vrf_ip6_input_dst(skb, vrf_dev, orig_iif);

	skb = vrf_rcv_nfhook(NFPROTO_IPV6, NF_INET_PRE_ROUTING, skb, vrf_dev);
out:
	return skb;
}