From: Justin Pettit Date: Wed, 22 Oct 2008 00:16:28 +0000 (-0700) Subject: Fix crash when SNAT support is built and traffic is in-band. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2f58a5d0031edb0cc90454ccb0883d61120e63a8;p=openvswitch Fix crash when SNAT support is built and traffic is in-band. In order to make netfilter happy, we have to create a fake routing table entry. Unfortunately, the kernel really doesn't like this when it actually needs to make use of it. This code now removes the link between the packet and the fake routing entry when the packet is being sent to a local port. --- diff --git a/datapath/datapath.c b/datapath/datapath.c index 8f01386a..27152c86 100644 --- a/datapath/datapath.c +++ b/datapath/datapath.c @@ -631,6 +631,9 @@ int dp_output_port(struct datapath *dp, struct sk_buff *skb, int out_port, case OFPP_LOCAL: { struct net_device *dev = dp->netdev; +#ifdef SUPPORT_SNAT + snat_local_in(skb); +#endif return dev ? dp_dev_recv(dev, skb) : -ESRCH; } diff --git a/datapath/nx_act_snat.c b/datapath/nx_act_snat.c index 83d505fb..dcef792e 100644 --- a/datapath/nx_act_snat.c +++ b/datapath/nx_act_snat.c @@ -97,6 +97,17 @@ done: spin_unlock_irqrestore(&p->lock, flags); } +/* When the packet is bound for a local interface, strip off the fake + * routing table. + */ +void snat_local_in(struct sk_buff *skb) +{ + if (skb->dst == (struct dst_entry *)&__fake_rtable) { + dst_release(skb->dst); + skb->dst = NULL; + } +} + /* Check whether destination IP's address is in the IP->MAC mappings. * If it is, then overwrite the destination MAC with the value from the * cache. @@ -147,6 +158,9 @@ snat_pre_route_finish(struct sk_buff *skb) { struct net_bridge_port *p = skb->dev->br_port; + skb->dst = (struct dst_entry *)&__fake_rtable; + dst_hold(skb->dst); + /* If SNAT is configured for this input device, check the IP->MAC * mappings to see if we should update the destination MAC. */ if (p->snat) @@ -308,9 +322,6 @@ snat_pre_route(struct sk_buff *skb) if (pskb_trim_rcsum(skb, len)) goto ipv4_error; - skb->dst = (struct dst_entry *)&__fake_rtable; - dst_hold(skb->dst); - return NF_HOOK(PF_INET, NF_INET_PRE_ROUTING, skb, skb->dev, NULL, snat_pre_route_finish); diff --git a/datapath/nx_act_snat.h b/datapath/nx_act_snat.h index 1e549d8a..cb68d60a 100644 --- a/datapath/nx_act_snat.h +++ b/datapath/nx_act_snat.h @@ -28,6 +28,7 @@ struct snat_conf { #define MAC_TIMEOUT_DEFAULT 120 +void snat_local_in(struct sk_buff *skb); int snat_pre_route(struct sk_buff *skb); void snat_skb(struct datapath *dp, struct sk_buff *skb, int out_port); void snat_maint(struct net_bridge_port *p);