From: Pablo Neira Ayuso <pablo@netfilter.org>
To: netfilter-devel@vger.kernel.org
Cc: davem@davemloft.net, netdev@vger.kernel.org
Subject: [PATCH 22/34] ipvs: support ipv4 in ipv6 and ipv6 in ipv4 tunnel forwarding
Date: Mon, 29 Sep 2014 14:39:11 +0200 [thread overview]
Message-ID: <1411994363-8451-23-git-send-email-pablo@netfilter.org> (raw)
In-Reply-To: <1411994363-8451-1-git-send-email-pablo@netfilter.org>
From: Alex Gartrell <agartrell@fb.com>
Pull the common logic for preparing an skb to prepend the header into a
single function and then set fields such that they can be used in either
case (generalize tos and tclass to dscp, hop_limit and ttl to ttl, etc)
Signed-off-by: Alex Gartrell <agartrell@fb.com>
Acked-by: Julian Anastasov <ja@ssi.bg>
Signed-off-by: Simon Horman <horms@verge.net.au>
---
net/netfilter/ipvs/ip_vs_conn.c | 12 +++-
net/netfilter/ipvs/ip_vs_xmit.c | 148 ++++++++++++++++++++++++++++-----------
2 files changed, 117 insertions(+), 43 deletions(-)
diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c
index fdb4880..13e9cee 100644
--- a/net/netfilter/ipvs/ip_vs_conn.c
+++ b/net/netfilter/ipvs/ip_vs_conn.c
@@ -488,7 +488,12 @@ static inline void ip_vs_bind_xmit(struct ip_vs_conn *cp)
break;
case IP_VS_CONN_F_TUNNEL:
- cp->packet_xmit = ip_vs_tunnel_xmit;
+#ifdef CONFIG_IP_VS_IPV6
+ if (cp->daf == AF_INET6)
+ cp->packet_xmit = ip_vs_tunnel_xmit_v6;
+ else
+#endif
+ cp->packet_xmit = ip_vs_tunnel_xmit;
break;
case IP_VS_CONN_F_DROUTE:
@@ -514,7 +519,10 @@ static inline void ip_vs_bind_xmit_v6(struct ip_vs_conn *cp)
break;
case IP_VS_CONN_F_TUNNEL:
- cp->packet_xmit = ip_vs_tunnel_xmit_v6;
+ if (cp->daf == AF_INET6)
+ cp->packet_xmit = ip_vs_tunnel_xmit_v6;
+ else
+ cp->packet_xmit = ip_vs_tunnel_xmit;
break;
case IP_VS_CONN_F_DROUTE:
diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c
index fa2fdd7..91f17c1 100644
--- a/net/netfilter/ipvs/ip_vs_xmit.c
+++ b/net/netfilter/ipvs/ip_vs_xmit.c
@@ -824,6 +824,81 @@ tx_error:
}
#endif
+/* When forwarding a packet, we must ensure that we've got enough headroom
+ * for the encapsulation packet in the skb. This also gives us an
+ * opportunity to figure out what the payload_len, dsfield, ttl, and df
+ * values should be, so that we won't need to look at the old ip header
+ * again
+ */
+static struct sk_buff *
+ip_vs_prepare_tunneled_skb(struct sk_buff *skb, int skb_af,
+ unsigned int max_headroom, __u8 *next_protocol,
+ __u32 *payload_len, __u8 *dsfield, __u8 *ttl,
+ __be16 *df)
+{
+ struct sk_buff *new_skb = NULL;
+ struct iphdr *old_iph = NULL;
+#ifdef CONFIG_IP_VS_IPV6
+ struct ipv6hdr *old_ipv6h = NULL;
+#endif
+
+ if (skb_headroom(skb) < max_headroom || skb_cloned(skb)) {
+ new_skb = skb_realloc_headroom(skb, max_headroom);
+ if (!new_skb)
+ goto error;
+ consume_skb(skb);
+ skb = new_skb;
+ }
+
+#ifdef CONFIG_IP_VS_IPV6
+ if (skb_af == AF_INET6) {
+ old_ipv6h = ipv6_hdr(skb);
+ *next_protocol = IPPROTO_IPV6;
+ if (payload_len)
+ *payload_len =
+ ntohs(old_ipv6h->payload_len) +
+ sizeof(*old_ipv6h);
+ *dsfield = ipv6_get_dsfield(old_ipv6h);
+ *ttl = old_ipv6h->hop_limit;
+ if (df)
+ *df = 0;
+ } else
+#endif
+ {
+ old_iph = ip_hdr(skb);
+ /* Copy DF, reset fragment offset and MF */
+ if (df)
+ *df = (old_iph->frag_off & htons(IP_DF));
+ *next_protocol = IPPROTO_IPIP;
+
+ /* fix old IP header checksum */
+ ip_send_check(old_iph);
+ *dsfield = ipv4_get_dsfield(old_iph);
+ *ttl = old_iph->ttl;
+ if (payload_len)
+ *payload_len = ntohs(old_iph->tot_len);
+ }
+
+ return skb;
+error:
+ kfree_skb(skb);
+ return ERR_PTR(-ENOMEM);
+}
+
+static inline int __tun_gso_type_mask(int encaps_af, int orig_af)
+{
+ if (encaps_af == AF_INET) {
+ if (orig_af == AF_INET)
+ return SKB_GSO_IPIP;
+
+ return SKB_GSO_SIT;
+ }
+
+ /* GSO: we need to provide proper SKB_GSO_ value for IPv6:
+ * SKB_GSO_SIT/IPV6
+ */
+ return 0;
+}
/*
* IP Tunneling transmitter
@@ -852,9 +927,11 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
struct rtable *rt; /* Route to the other host */
__be32 saddr; /* Source for tunnel */
struct net_device *tdev; /* Device to other host */
- struct iphdr *old_iph = ip_hdr(skb);
- u8 tos = old_iph->tos;
- __be16 df;
+ __u8 next_protocol = 0;
+ __u8 dsfield = 0;
+ __u8 ttl = 0;
+ __be16 df = 0;
+ __be16 *dfp = NULL;
struct iphdr *iph; /* Our new IP header */
unsigned int max_headroom; /* The extra header space needed */
int ret, local;
@@ -877,29 +954,21 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
rt = skb_rtable(skb);
tdev = rt->dst.dev;
- /* Copy DF, reset fragment offset and MF */
- df = sysctl_pmtu_disc(ipvs) ? old_iph->frag_off & htons(IP_DF) : 0;
-
/*
* Okay, now see if we can stuff it in the buffer as-is.
*/
max_headroom = LL_RESERVED_SPACE(tdev) + sizeof(struct iphdr);
- if (skb_headroom(skb) < max_headroom || skb_cloned(skb)) {
- struct sk_buff *new_skb =
- skb_realloc_headroom(skb, max_headroom);
-
- if (!new_skb)
- goto tx_error;
- consume_skb(skb);
- skb = new_skb;
- old_iph = ip_hdr(skb);
- }
-
- /* fix old IP header checksum */
- ip_send_check(old_iph);
+ /* We only care about the df field if sysctl_pmtu_disc(ipvs) is set */
+ dfp = sysctl_pmtu_disc(ipvs) ? &df : NULL;
+ skb = ip_vs_prepare_tunneled_skb(skb, cp->af, max_headroom,
+ &next_protocol, NULL, &dsfield,
+ &ttl, dfp);
+ if (IS_ERR(skb))
+ goto tx_error;
- skb = iptunnel_handle_offloads(skb, false, SKB_GSO_IPIP);
+ skb = iptunnel_handle_offloads(
+ skb, false, __tun_gso_type_mask(AF_INET, cp->af));
if (IS_ERR(skb))
goto tx_error;
@@ -916,11 +985,11 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
iph->version = 4;
iph->ihl = sizeof(struct iphdr)>>2;
iph->frag_off = df;
- iph->protocol = IPPROTO_IPIP;
- iph->tos = tos;
+ iph->protocol = next_protocol;
+ iph->tos = dsfield;
iph->daddr = cp->daddr.ip;
iph->saddr = saddr;
- iph->ttl = old_iph->ttl;
+ iph->ttl = ttl;
ip_select_ident(skb, NULL);
/* Another hack: avoid icmp_send in ip_fragment */
@@ -953,7 +1022,10 @@ ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
struct rt6_info *rt; /* Route to the other host */
struct in6_addr saddr; /* Source for tunnel */
struct net_device *tdev; /* Device to other host */
- struct ipv6hdr *old_iph = ipv6_hdr(skb);
+ __u8 next_protocol = 0;
+ __u32 payload_len = 0;
+ __u8 dsfield = 0;
+ __u8 ttl = 0;
struct ipv6hdr *iph; /* Our new IP header */
unsigned int max_headroom; /* The extra header space needed */
int ret, local;
@@ -981,19 +1053,14 @@ ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
*/
max_headroom = LL_RESERVED_SPACE(tdev) + sizeof(struct ipv6hdr);
- if (skb_headroom(skb) < max_headroom || skb_cloned(skb)) {
- struct sk_buff *new_skb =
- skb_realloc_headroom(skb, max_headroom);
-
- if (!new_skb)
- goto tx_error;
- consume_skb(skb);
- skb = new_skb;
- old_iph = ipv6_hdr(skb);
- }
+ skb = ip_vs_prepare_tunneled_skb(skb, cp->af, max_headroom,
+ &next_protocol, &payload_len,
+ &dsfield, &ttl, NULL);
+ if (IS_ERR(skb))
+ goto tx_error;
- /* GSO: we need to provide proper SKB_GSO_ value for IPv6 */
- skb = iptunnel_handle_offloads(skb, false, 0); /* SKB_GSO_SIT/IPV6 */
+ skb = iptunnel_handle_offloads(
+ skb, false, __tun_gso_type_mask(AF_INET6, cp->af));
if (IS_ERR(skb))
goto tx_error;
@@ -1008,14 +1075,13 @@ ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
*/
iph = ipv6_hdr(skb);
iph->version = 6;
- iph->nexthdr = IPPROTO_IPV6;
- iph->payload_len = old_iph->payload_len;
- be16_add_cpu(&iph->payload_len, sizeof(*old_iph));
+ iph->nexthdr = next_protocol;
+ iph->payload_len = htons(payload_len);
memset(&iph->flow_lbl, 0, sizeof(iph->flow_lbl));
- ipv6_change_dsfield(iph, 0, ipv6_get_dsfield(old_iph));
+ ipv6_change_dsfield(iph, 0, dsfield);
iph->daddr = cp->daddr.in6;
iph->saddr = saddr;
- iph->hop_limit = old_iph->hop_limit;
+ iph->hop_limit = ttl;
/* Another hack: avoid icmp_send in ip_fragment */
skb->ignore_df = 1;
--
1.7.10.4
next prev parent reply other threads:[~2014-09-29 12:38 UTC|newest]
Thread overview: 47+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-09-29 12:38 [PATCH 00/34] pull request: netfilter/ipvs updates for net-next Pablo Neira Ayuso
2014-09-29 12:38 ` [PATCH 01/34] netfilter: fix compilation of masquerading without IP_NF_TARGET_MASQUERADE Pablo Neira Ayuso
2014-09-29 12:38 ` [PATCH 02/34] netfilter: nf_tables: add NFTA_MASQ_UNSPEC to nft_masq_attributes Pablo Neira Ayuso
2014-09-29 12:38 ` [PATCH 03/34] netfilter: NFT_CHAIN_NAT_IPV* is independent of NFT_NAT Pablo Neira Ayuso
2014-09-29 12:38 ` [PATCH 04/34] netfilter: masquerading needs to be independent of x_tables in Kconfig Pablo Neira Ayuso
2014-09-29 12:38 ` [PATCH 05/34] netfilter: ipset: Fix static checker warning in ip_set_core.c Pablo Neira Ayuso
2014-09-29 12:38 ` [PATCH 06/34] netfilter: ipset: Add skbinfo extension kernel support in the ipset core Pablo Neira Ayuso
2014-09-29 12:38 ` [PATCH 07/34] netfilter: ipset: Add skbinfo extension kernel support for the bitmap set types Pablo Neira Ayuso
2014-09-29 12:38 ` [PATCH 08/34] netfilter: ipset: Add skbinfo extension kernel support for the hash " Pablo Neira Ayuso
2014-09-29 12:38 ` [PATCH 09/34] netfilter: ipset: Add skbinfo extension kernel support for the list set type Pablo Neira Ayuso
2014-09-29 12:38 ` [PATCH 10/34] netfilter: ipset: Add skbinfo extension support to SET target Pablo Neira Ayuso
2014-09-29 12:39 ` [PATCH 11/34] netfilter: ipset: send nonzero skbinfo extensions only Pablo Neira Ayuso
2014-09-29 12:39 ` [PATCH 12/34] netfilter: ipset: hash:mac type added to ipset Pablo Neira Ayuso
2014-09-29 12:39 ` [PATCH 13/34] ipvs: Add simple weighted failover scheduler Pablo Neira Ayuso
2014-09-29 12:39 ` [PATCH 14/34] ipvs: Add destination address family to netlink interface Pablo Neira Ayuso
2014-09-29 12:39 ` [PATCH 15/34] ipvs: Supply destination addr family to ip_vs_{lookup_dest,find_dest} Pablo Neira Ayuso
2014-09-29 12:39 ` [PATCH 16/34] ipvs: Pass destination address family to ip_vs_trash_get_dest Pablo Neira Ayuso
2014-09-29 12:39 ` [PATCH 17/34] ipvs: Supply destination address family to ip_vs_conn_new Pablo Neira Ayuso
2014-09-29 12:39 ` [PATCH 18/34] ipvs: prevent mixing heterogeneous pools and synchronization Pablo Neira Ayuso
2014-09-29 16:17 ` Sergei Shtylyov
2014-09-30 2:21 ` Simon Horman
2014-09-29 12:39 ` [PATCH 19/34] ipvs: Pull out crosses_local_route_boundary logic Pablo Neira Ayuso
2014-09-29 12:39 ` [PATCH 20/34] ipvs: Pull out update_pmtu code Pablo Neira Ayuso
2014-09-29 12:39 ` [PATCH 21/34] ipvs: Add generic ensure_mtu_is_adequate to handle mixed pools Pablo Neira Ayuso
2014-09-29 12:39 ` Pablo Neira Ayuso [this message]
2014-09-29 12:39 ` [PATCH 23/34] ipvs: address family of LBLC entry depends on svc family Pablo Neira Ayuso
2014-09-29 12:39 ` [PATCH 24/34] ipvs: address family of LBLCR " Pablo Neira Ayuso
2014-09-29 12:39 ` [PATCH 25/34] ipvs: use correct address family in scheduler logs Pablo Neira Ayuso
2014-09-29 12:39 ` [PATCH 26/34] ipvs: use the new dest addr family field Pablo Neira Ayuso
2014-09-29 12:39 ` [PATCH 27/34] ipvs: Allow heterogeneous pools now that we support them Pablo Neira Ayuso
2014-09-29 12:39 ` [PATCH 28/34] netfilter: nfnetlink: use original skbuff when committing/aborting Pablo Neira Ayuso
2014-09-29 12:39 ` [PATCH 29/34] netfilter: nf_tables: export rule-set generation ID Pablo Neira Ayuso
2014-09-29 12:39 ` [PATCH 30/34] net/netfilter/x_tables.c: use __seq_open_private() Pablo Neira Ayuso
2014-09-29 16:07 ` Sergei Shtylyov
2014-09-29 12:39 ` [PATCH 31/34] netfilter: bridge: nf_bridge_copy_header as static inline in header Pablo Neira Ayuso
2014-09-29 12:39 ` [PATCH 32/34] netfilter: bridge: move br_netfilter out of the core Pablo Neira Ayuso
2014-09-29 22:04 ` Eric Dumazet
2014-09-29 23:17 ` Florian Westphal
2014-09-30 8:56 ` Pablo Neira Ayuso
2014-09-30 15:58 ` Stephen Hemminger
2014-10-01 10:33 ` Pablo Neira Ayuso
2014-09-29 12:39 ` [PATCH 33/34] netfilter: nf_tables: store and dump set policy Pablo Neira Ayuso
2014-09-29 16:14 ` Sergei Shtylyov
2014-10-01 13:47 ` Arturo Borrero Gonzalez
2014-09-29 12:39 ` [PATCH 34/34] netfilter: conntrack: disable generic tracking for known protocols Pablo Neira Ayuso
2014-09-29 18:54 ` [PATCH 00/34] pull request: netfilter/ipvs updates for net-next David Miller
2014-09-30 0:22 ` Simon Horman
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1411994363-8451-23-git-send-email-pablo@netfilter.org \
--to=pablo@netfilter.org \
--cc=davem@davemloft.net \
--cc=netdev@vger.kernel.org \
--cc=netfilter-devel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).