From: Ben Pfaff Date: Tue, 19 May 2009 22:37:10 +0000 (-0700) Subject: Remove vestigial SNAT support. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=126e1d03745606faace00c5b0151f182a3e0e43a;p=openvswitch Remove vestigial SNAT support. --- diff --git a/configure.ac b/configure.ac index c8962607..cf17393c 100644 --- a/configure.ac +++ b/configure.ac @@ -59,7 +59,6 @@ OVS_CHECK_USERSPACE OVS_CHECK_NDEBUG OVS_CHECK_NETLINK OVS_CHECK_OPENSSL -OVS_CHECK_SNAT OVS_CHECK_LOGDIR OVS_CHECK_CURSES OVS_CHECK_LINUX_VT_H diff --git a/datapath/Modules.mk b/datapath/Modules.mk index 9853f211..1b5de4ab 100644 --- a/datapath/Modules.mk +++ b/datapath/Modules.mk @@ -15,7 +15,6 @@ openvswitch_sources = \ dp_dev.c \ dp_notify.c \ flow.c \ - snat.c \ table.c openvswitch_headers = \ @@ -23,8 +22,7 @@ openvswitch_headers = \ compat.h \ datapath.h \ dp_dev.h \ - flow.h \ - snat.h + flow.h dist_sources = $(foreach module,$(dist_modules),$($(module)_sources)) dist_headers = $(foreach module,$(dist_modules),$($(module)_headers)) diff --git a/datapath/actions.c b/datapath/actions.c index a065e7e8..6bbb9f99 100644 --- a/datapath/actions.c +++ b/datapath/actions.c @@ -19,7 +19,6 @@ #include "dp_dev.h" #include "actions.h" #include "openvswitch/datapath-protocol.h" -#include "snat.h" struct sk_buff * make_writable(struct sk_buff *skb, gfp_t gfp) @@ -273,55 +272,6 @@ static inline unsigned packet_length(const struct sk_buff *skb) return length; } -#ifdef SUPPORT_SNAT -static int -dp_xmit_skb_finish(struct sk_buff *skb) -{ - /* Copy back the Ethernet header that was stowed earlier. */ - if (skb->protocol == htons(ETH_P_IP) && snat_copy_header(skb)) { - kfree_skb(skb); - return -EINVAL; - } - skb_reset_mac_header(skb); - - if (packet_length(skb) > skb->dev->mtu && !skb_is_gso(skb)) { - printk("dropped over-mtu packet: %d > %d\n", - packet_length(skb), skb->dev->mtu); - kfree_skb(skb); - return -E2BIG; - } - - skb_push(skb, ETH_HLEN); - dev_queue_xmit(skb); - - return 0; -} - -int dp_xmit_skb(struct sk_buff *skb) -{ - int len = skb->len; - int err; - - skb_pull(skb, ETH_HLEN); - - /* The ip_fragment function does not copy the Ethernet header into - * the newly generated frames, so stow the original. */ - if (skb->protocol == htons(ETH_P_IP)) - snat_save_header(skb); - - if (skb->protocol == htons(ETH_P_IP) && - skb->len > skb->dev->mtu && - !skb_is_gso(skb)) { - err = ip_fragment(skb, dp_xmit_skb_finish); - } else { - err = dp_xmit_skb_finish(skb); - } - if (err) - return err; - - return len; -} -#else int dp_xmit_skb(struct sk_buff *skb) { struct datapath *dp = skb->dev->br_port->dp; @@ -338,7 +288,6 @@ int dp_xmit_skb(struct sk_buff *skb) return len; } -#endif static void do_output(struct datapath *dp, struct sk_buff *skb, int out_port) @@ -461,12 +410,6 @@ int execute_actions(struct datapath *dp, struct sk_buff *skb, case ODPAT_SET_TP_DST: skb = set_tp_port(skb, key, &a->tp_port, gfp); break; - -#ifdef SUPPORT_SNAT - case ODPAT_SNAT: - snat_skb(dp, skb, a->snat.port, gfp); - break; -#endif } if (!skb) return -ENOMEM; diff --git a/datapath/datapath.c b/datapath/datapath.c index e3e50308..41921069 100644 --- a/datapath/datapath.c +++ b/datapath/datapath.c @@ -41,7 +41,6 @@ #include "openvswitch/datapath-protocol.h" #include "datapath.h" -#include "snat.h" #include "actions.h" #include "dp_dev.h" #include "flow.h" @@ -81,9 +80,6 @@ static DEFINE_MUTEX(dp_mutex); /* Number of milliseconds between runs of the maintenance thread. */ #define MAINT_SLEEP_MSECS 1000 -#ifdef SUPPORT_SNAT -static int dp_maint_func(void *data); -#endif static int new_nbp(struct datapath *, struct net_device *, int port_no); /* Must be called with rcu_read_lock or dp_mutex. */ @@ -245,12 +241,6 @@ static int create_dp(int dp_idx, const char __user *devnamep) if (!dp->stats_percpu) goto err_destroy_local_port; -#ifdef SUPPORT_SNAT - dp->dp_task = kthread_run(dp_maint_func, dp, "dp%d", dp_idx); - if (IS_ERR(dp->dp_task)) - goto err_destroy_stats_percpu; -#endif - rcu_assign_pointer(dps[dp_idx], dp); mutex_unlock(&dp_mutex); rtnl_unlock(); @@ -260,10 +250,6 @@ static int create_dp(int dp_idx, const char __user *devnamep) return 0; -#ifdef SUPPORT_SNAT -err_destroy_stats_percpu: - free_percpu(dp->stats_percpu); -#endif err_destroy_local_port: dp_del_port(dp->ports[ODPP_LOCAL], NULL); err_destroy_table: @@ -286,11 +272,6 @@ static void do_destroy_dp(struct datapath *dp, struct list_head *dp_devs) struct net_bridge_port *p, *n; int i; -#ifdef SUPPORT_SNAT - send_sig(SIGKILL, dp->dp_task, 0); - kthread_stop(dp->dp_task); -#endif - if (dp_del_dp_hook) dp_del_dp_hook(dp); @@ -353,9 +334,6 @@ static int new_nbp(struct datapath *dp, struct net_device *dev, int port_no) dev_set_promiscuity(dev, 1); dev_hold(dev); p->port_no = port_no; -#ifdef SUPPORT_SNAT - spin_lock_init(&p->lock); -#endif p->dp = dp; p->dev = dev; if (!is_dp_dev(dev)) @@ -438,17 +416,6 @@ out: return err; } -/* Free any SNAT configuration on the port. */ -static void free_snat(struct net_bridge_port *p) -{ -#ifdef SUPPORT_SNAT - unsigned long int flags; - spin_lock_irqsave(&p->lock, flags); - snat_free_conf(p); - spin_unlock_irqrestore(&p->lock, flags); -#endif /* !SUPPORT_SNAT */ -} - int dp_del_port(struct net_bridge_port *p, struct list_head *dp_devs) { ASSERT_RTNL(); @@ -469,7 +436,6 @@ int dp_del_port(struct net_bridge_port *p, struct list_head *dp_devs) /* Then wait until no one is still using it, and destroy it. */ synchronize_rcu(); - free_snat(p); if (is_dp_dev(p->dev)) { dp_dev_destroy(p->dev); @@ -523,30 +489,6 @@ out: return err; } -#ifdef SUPPORT_SNAT -static int dp_maint_func(void *data) -{ - struct datapath *dp = (struct datapath *) data; - - allow_signal(SIGKILL); - while (!signal_pending(current)) { - struct net_bridge_port *p; - - /* Expire old SNAT entries */ - rcu_read_lock(); - list_for_each_entry_rcu (p, &dp->port_list, node) - snat_maint(p); - rcu_read_unlock(); - msleep_interruptible(MAINT_SLEEP_MSECS); - } - while (!kthread_should_stop()) { - set_current_state(TASK_UNINTERRUPTIBLE); - schedule(); - } - return 0; -} -#endif - /* Must be called with rcu_read_lock. */ static void do_port_input(struct net_bridge_port *p, struct sk_buff *skb) @@ -559,12 +501,6 @@ do_port_input(struct net_bridge_port *p, struct sk_buff *skb) if (!skb) return; -#ifdef SUPPORT_SNAT - /* Check if this packet needs early SNAT processing. */ - if (snat_pre_route(skb)) - return; -#endif - /* Push the Ethernet header back on. */ skb_push(skb, ETH_HLEN); skb_reset_mac_header(skb); @@ -809,15 +745,6 @@ static int validate_actions(const struct sw_flow_actions *actions) for (i = 0; i < actions->n_actions; i++) { const union odp_action *a = &actions->actions[i]; switch (a->type) { - case ODPAT_SNAT: - if (a->snat.port >= DP_MAX_PORTS) - return -EINVAL; -#ifndef SUPPORT_SNAT - if (net_ratelimit()) - printk(KERN_ERR "SNAT not supported\n"); - return -EOPNOTSUPP; -#endif - case ODPAT_OUTPUT: if (a->output.port >= DP_MAX_PORTS) return -EINVAL; @@ -1403,9 +1330,6 @@ static long openvswitch_ioctl(struct file *f, unsigned int cmd, int dp_idx = iminor(f->f_dentry->d_inode); struct datapath *dp; int drop_frags, listeners, port_no; -#ifdef SUPPORT_SNAT - struct odp_snat_config osc; -#endif int err; /* Handle commands with special locking requirements up front. */ @@ -1507,23 +1431,6 @@ static long openvswitch_ioctl(struct file *f, unsigned int cmd, err = do_execute(dp, (struct odp_execute __user *)argp); break; -#ifdef SUPPORT_SNAT - case ODP_SNAT_ADD_PORT: - err = -EFAULT; - if (copy_from_user(&osc, (struct odp_snat_config __user *)argp, - sizeof osc)) - break; - err = snat_add_port(dp, &osc); - break; - - case ODP_SNAT_DEL_PORT: - err = get_user(port_no, (int __user *)argp); - if (err) - break; - err = snat_del_port(dp, port_no); - break; -#endif - default: err = -ENOIOCTLCMD; break; diff --git a/datapath/datapath.h b/datapath/datapath.h index 66bb01cf..102b27f3 100644 --- a/datapath/datapath.h +++ b/datapath/datapath.h @@ -58,10 +58,6 @@ struct datapath { struct mutex mutex; int dp_idx; -#ifdef SUPPORT_SNAT - struct task_struct *dp_task; /* Kernel thread for maintenance. */ -#endif - #ifdef SUPPORT_SYSFS struct kobject ifobj; #endif @@ -94,10 +90,6 @@ struct net_bridge_port { struct net_device *dev; #ifdef SUPPORT_SYSFS struct kobject kobj; -#endif -#ifdef SUPPORT_SNAT - spinlock_t lock; - struct snat_conf *snat; #endif struct list_head node; /* Element in datapath.ports. */ }; diff --git a/datapath/dp_dev.c b/datapath/dp_dev.c index d0bf9494..8a749dbc 100644 --- a/datapath/dp_dev.c +++ b/datapath/dp_dev.c @@ -8,7 +8,6 @@ #include "datapath.h" #include "dp_dev.h" -#include "snat.h" struct datapath *dp_dev_get_dp(struct net_device *netdev) { @@ -26,9 +25,6 @@ int dp_dev_recv(struct net_device *netdev, struct sk_buff *skb) { struct dp_dev *dp_dev = dp_dev_priv(netdev); int len; -#ifdef SUPPORT_SNAT - snat_internal_in(skb); -#endif len = skb->len; skb->pkt_type = PACKET_HOST; skb->protocol = eth_type_trans(skb, netdev); diff --git a/datapath/linux-2.6/.gitignore b/datapath/linux-2.6/.gitignore index 1f540d5d..af5821a2 100644 --- a/datapath/linux-2.6/.gitignore +++ b/datapath/linux-2.6/.gitignore @@ -15,7 +15,6 @@ /linux-2.6 /modules.order /random32.c -/snat.c /table.c /tmp /veth.c diff --git a/datapath/linux-2.6/Kbuild.in b/datapath/linux-2.6/Kbuild.in index 350f241b..f08eb9c5 100644 --- a/datapath/linux-2.6/Kbuild.in +++ b/datapath/linux-2.6/Kbuild.in @@ -12,7 +12,6 @@ EXTRA_CFLAGS := -DVERSION=\"$(VERSION)\" EXTRA_CFLAGS += -I$(srcdir)/.. EXTRA_CFLAGS += -I$(builddir)/.. EXTRA_CFLAGS += -I$(top_srcdir)/include -EXTRA_CFLAGS += @SUPPORT_SNAT@ ifeq '$(BUILDNR)' '0' EXTRA_CFLAGS += -DBUILDNR=\"\" else diff --git a/datapath/snat.c b/datapath/snat.c deleted file mode 100644 index 6b9be469..00000000 --- a/datapath/snat.c +++ /dev/null @@ -1,637 +0,0 @@ -#ifdef SUPPORT_SNAT -/* - * Distributed under the terms of the GNU GPL version 2. - * Copyright (c) 2008, 2009 Nicira Networks - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "actions.h" -#include "snat.h" - -/* Cache of IP->MAC mappings on the side hidden by the SNAT */ -struct snat_mapping { - struct list_head node; - u32 ip_addr; /* Stored in network-order */ - u8 hw_addr[ETH_ALEN]; - unsigned long used; /* Last used time (in jiffies). */ - - struct rcu_head rcu; -}; - -struct snat_conf { - u32 ip_addr_start; /* Stored in host-order */ - u32 ip_addr_end; /* Stored in host-order */ - u16 mac_timeout; - - u8 mac_addr[ETH_ALEN]; - - struct list_head mappings; /* List of snat_mapping entries */ -}; - -#define MAC_TIMEOUT_DEFAULT 120 - -/* We need these fake structures to make netfilter happy -- - * lots of places assume that skb->dst != NULL, which isn't - * all that unreasonable. - * - * Currently, we fill in the PMTU entry because netfilter - * refragmentation needs it, and the rt_flags entry because - * ipt_REJECT needs it. Future netfilter modules might - * require us to fill additional fields. */ -static struct net_device __fake_net_device = { - .hard_header_len = ETH_HLEN -}; - -static struct rtable __fake_rtable = { - .u = { - .dst = { - .__refcnt = ATOMIC_INIT(1), - .dev = &__fake_net_device, - .path = &__fake_rtable.u.dst, - .metrics = {[RTAX_MTU - 1] = 1500}, - .flags = DST_NOXFRM, - } - }, - .rt_flags = 0, -}; - -/* Define ARP for IP since the Linux headers don't do it cleanly. */ -struct ip_arphdr { - u16 ar_hrd; - u16 ar_pro; - u8 ar_hln; - u8 ar_pln; - u16 ar_op; - u8 ar_sha[ETH_ALEN]; - u32 ar_sip; - u8 ar_tha[ETH_ALEN]; - u32 ar_tip; -} __attribute__((packed)); - -static inline struct nf_bridge_info *nf_bridge_alloc(struct sk_buff *skb) -{ - skb->nf_bridge = kzalloc(sizeof(struct nf_bridge_info), GFP_ATOMIC); - if (likely(skb->nf_bridge)) - atomic_set(&(skb->nf_bridge->use), 1); - - return skb->nf_bridge; -} - -/* Save a copy of the original Ethernet header. */ -void snat_save_header(struct sk_buff *skb) -{ - int header_size = ETH_HLEN + nf_bridge_encap_header_len(skb); - - if (!skb->nf_bridge) - return; - - skb_copy_from_linear_data_offset(skb, -header_size, - skb->nf_bridge->data, header_size); -} - -/* Restore a saved Ethernet header. */ -int snat_copy_header(struct sk_buff *skb) -{ - int err; - int header_size = ETH_HLEN + nf_bridge_encap_header_len(skb); - - if (!skb->nf_bridge) - return 0; - - err = skb_cow_head(skb, header_size); - if (err) - return err; - - skb_copy_to_linear_data_offset(skb, -header_size, - skb->nf_bridge->data, header_size); - __skb_push(skb, nf_bridge_encap_header_len(skb)); - return 0; -} - -/* Push the Ethernet header back on and tranmit the packet. */ -static int -dp_xmit_skb_push(struct sk_buff *skb) -{ - skb_push(skb, ETH_HLEN); - return dp_xmit_skb(skb); -} - -/* Perform maintainence related to a SNAT'd interface. Currently, this only - * checks whether MAC->IP bindings have expired. - * - * Called with the RCU read lock */ -void -snat_maint(struct net_bridge_port *p) -{ - struct snat_conf *sc; - struct snat_mapping *m, *n; - unsigned long flags; - unsigned long timeout; - - spin_lock_irqsave(&p->lock, flags); - sc = p->snat; - if (!sc) - goto done; - - timeout = sc->mac_timeout * HZ; - - list_for_each_entry_safe (m, n, &sc->mappings, node) { - if (time_after(jiffies, m->used + timeout)) { - list_del(&m->node); - kfree(m); - } - } - -done: - spin_unlock_irqrestore(&p->lock, flags); -} - -/* When the packet is bound for an internal interface, strip off the fake - * routing table. - */ -void snat_internal_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. - * - * Returns -1 if there is a problem, otherwise 0. */ -static int -dnat_mac(struct net_bridge_port *p, struct sk_buff *skb) -{ - struct snat_conf *sc = p->snat; - struct iphdr *iph = ip_hdr(skb); - struct ethhdr *eh = eth_hdr(skb); - struct snat_mapping *m; - - if (skb->protocol != htons(ETH_P_IP)) - return 0; - - list_for_each_entry (m, &sc->mappings, node) { - if (m->ip_addr == iph->daddr){ - /* Found it! */ - skb = make_writable(skb, GFP_ATOMIC); - if (!skb) - return -1; - m->used = jiffies; - memcpy(eh->h_dest, m->hw_addr, ETH_ALEN); - break; - } - } - - return 0; -} - -static int -__snat_this_address(struct snat_conf *sc, u32 ip_addr) -{ - if (sc) { - u32 h_ip_addr = ntohl(ip_addr); - return (h_ip_addr >= sc->ip_addr_start && - h_ip_addr <= sc->ip_addr_end); - } - return 0; -} - -static int -snat_this_address(struct net_bridge_port *p, u32 ip_addr) -{ - unsigned long int flags; - int retval; - - spin_lock_irqsave(&p->lock, flags); - retval = __snat_this_address(p->snat, ip_addr); - spin_unlock_irqrestore(&p->lock, flags); - - return retval; -} - -/* Must hold RCU lock. */ -static struct net_bridge_port * -get_nbp_by_ip_addr(struct datapath *dp, u32 ip_addr) -{ - struct net_bridge_port *p; - - list_for_each_entry_rcu (p, &dp->port_list, node) - if (snat_this_address(p, ip_addr)) - return p; - - return NULL; -} - -static int -snat_pre_route_finish(struct sk_buff *skb) -{ - struct net_bridge_port *p = skb->dev->br_port; - struct snat_conf *sc; - struct iphdr *iph = ip_hdr(skb); - unsigned long flags; - - skb->dst = (struct dst_entry *)&__fake_rtable; - dst_hold(skb->dst); - - /* Don't process packets that were not translated due to NAT */ - spin_lock_irqsave(&p->lock, flags); - sc = p->snat; - if (!__snat_this_address(sc, iph->daddr)) { - /* If SNAT is configured for this input device, check the - * IP->MAC mappings to see if we should update the destination - * MAC. */ - if (sc) - dnat_mac(skb->dev->br_port, skb); - - } - spin_unlock_irqrestore(&p->lock, flags); - - /* Pass the translated packet as input to the openvswitch stack, which - * consumes it. */ - skb_push(skb, ETH_HLEN); - skb_reset_mac_header(skb); - dp_process_received_packet(skb, p); - - return 0; -} - -/* Checks whether 'skb' is an ARP request for an SNAT'd interface. If - * so, it will generate a response. - * - * Returns 0 if the packet was not handled. Otherwise, -1 is returned - * and the caller is responsible for freeing 'skb'. */ -static int -handle_arp_snat(struct sk_buff *skb) -{ - struct net_bridge_port *s_nbp = skb->dev->br_port; - struct net_bridge_port *nat_nbp; - struct ip_arphdr *ah; - u8 mac_addr[ETH_ALEN]; - - if (!pskb_may_pull(skb, sizeof *ah)) - return 0; - - ah = (struct ip_arphdr *)arp_hdr(skb); - if ((ah->ar_op != htons(ARPOP_REQUEST)) - || ah->ar_hln != ETH_ALEN - || ah->ar_pro != htons(ETH_P_IP) - || ah->ar_pln != 4) - return 0; - - rcu_read_lock(); - nat_nbp = get_nbp_by_ip_addr(s_nbp->dp, ah->ar_tip); - if (!nat_nbp) { - rcu_read_unlock(); - return 0; - } - if (s_nbp == nat_nbp) - memcpy(mac_addr, s_nbp->dp->ports[ODPP_LOCAL]->dev->dev_addr, sizeof(mac_addr)); - else if (!is_zero_ether_addr(nat_nbp->snat->mac_addr)) - memcpy(mac_addr, nat_nbp->snat->mac_addr, sizeof(mac_addr)); - else { - rcu_read_unlock(); - return 0; - } - rcu_read_unlock(); - - arp_send(ARPOP_REPLY, ETH_P_ARP, ah->ar_sip, skb->dev, ah->ar_tip, - ah->ar_sha, mac_addr, ah->ar_sha); - - return -1; -} - -/* Checks whether 'skb' is a ping request for an SNAT'd interface. If - * so, it will generate a response. - * - * Returns 0 if the packet was not handled. Otherwise, -1 is returned - * and the caller is responsible for freeing 'skb'. */ -static int -handle_icmp_snat(struct sk_buff *skb) -{ - struct net_bridge_port *p = skb->dev->br_port; - struct ethhdr *eh; - struct iphdr *iph; - struct icmphdr *icmph; - u8 tmp_eth[ETH_ALEN]; - u32 tmp_ip; - struct sk_buff *nskb; - - /* We're only interested in addresses we rewrite. */ - iph = ip_hdr(skb); - if (!snat_this_address(p, iph->daddr)) { - return 0; - } - - /* Drop fragments and packets not long enough to hold the ICMP - * header. */ - if ((ntohs(iph->frag_off) & IP_OFFSET) != 0 || - !pskb_may_pull(skb, skb_transport_offset(skb) + 4)) - return 0; - - /* We only respond to echo requests to our address. Continue - * processing replies and other ICMP messages since they may be - * intended for NAT'd hosts. */ - icmph = icmp_hdr(skb); - if (icmph->type != ICMP_ECHO) - return 0; - - /* Send an echo reply in response */ - nskb = skb_copy(skb, GFP_ATOMIC); - if (!nskb) - return -1; - - /* Update Ethernet header. */ - eh = eth_hdr(nskb); - memcpy(tmp_eth, eh->h_dest, ETH_ALEN); - memcpy(eh->h_dest, eh->h_source, ETH_ALEN); - memcpy(eh->h_source, tmp_eth, ETH_ALEN); - - /* Update IP header. - * This is kind of busted, at least in that it doesn't check that the - * echoed IP options make sense. */ - iph = ip_hdr(nskb); - iph->id = 0; - iph->frag_off = 0; - iph->ttl = IPDEFTTL; - iph->check = 0; - tmp_ip = iph->daddr; - iph->daddr = iph->saddr; - iph->saddr = tmp_ip; - iph->check = ip_fast_csum((void *)iph, iph->ihl); - - /* Update ICMP header. */ - icmph = icmp_hdr(nskb); - icmph->type = ICMP_ECHOREPLY; - icmph->checksum = 0; - icmph->checksum = ip_compute_csum((void *)icmph, - nskb->tail - skb_transport_header(nskb)); - - dp_xmit_skb_push(nskb); - - return -1; -} - -/* Check if any SNAT maintenance needs to be done on 'skb' before it's - * checked against the datapath's tables. This includes DNAT - * modification based on prior SNAT action and responding to ARP and - * echo requests for the SNAT interface. - * - * Returns -1 if the packet was handled and consumed, 0 if the caller - * should continue to process 'skb'. - */ -int -snat_pre_route(struct sk_buff *skb) -{ - struct iphdr *iph; - int len; - - WARN_ON_ONCE(skb_network_offset(skb)); - if (skb->protocol == htons(ETH_P_ARP)) { - if (handle_arp_snat(skb)) - goto consume; - return 0; - } - else if (skb->protocol != htons(ETH_P_IP)) - return 0; - - if (!pskb_may_pull(skb, sizeof *iph)) - goto consume; - - iph = ip_hdr(skb); - if (iph->ihl < 5 || iph->version != 4) - goto consume; - - if (!pskb_may_pull(skb, ip_hdrlen(skb))) - goto consume; - skb_set_transport_header(skb, ip_hdrlen(skb)); - - /* Check if we need to echo reply for this address */ - iph = ip_hdr(skb); - if ((iph->protocol == IPPROTO_ICMP) && (handle_icmp_snat(skb))) - goto consume; - - iph = ip_hdr(skb); - if (unlikely(ip_fast_csum((void *)iph, iph->ihl))) - goto consume; - - len = ntohs(iph->tot_len); - if ((skb->len < len) || len < (iph->ihl*4)) - goto consume; - - if (pskb_trim_rcsum(skb, len)) - goto consume; - - nf_bridge_put(skb->nf_bridge); - if (!nf_bridge_alloc(skb)) - return 0; - - NF_HOOK(PF_INET, NF_INET_PRE_ROUTING, skb, skb->dev, NULL, - snat_pre_route_finish); - return -1; - -consume: - kfree_skb(skb); - return -1; -} - - -static int -snat_skb_finish(struct sk_buff *skb) -{ - NF_HOOK(PF_INET, NF_INET_POST_ROUTING, skb, NULL, skb->dev, - dp_xmit_skb_push); - - return 0; -} - -/* Update the MAC->IP mappings for the private side of the SNAT'd - * interface. */ -static void -update_mapping(struct net_bridge_port *p, const struct sk_buff *skb) -{ - unsigned long flags; - struct snat_conf *sc; - const struct iphdr *iph = ip_hdr(skb); - const struct ethhdr *eh = eth_hdr(skb); - struct snat_mapping *m; - - spin_lock_irqsave(&p->lock, flags); - sc = p->snat; - if (!sc) - goto done; - - list_for_each_entry (m, &sc->mappings, node) { - if (m->ip_addr == iph->saddr){ - memcpy(m->hw_addr, eh->h_source, ETH_ALEN); - m->used = jiffies; - goto done; - } - } - - m = kmalloc(sizeof *m, GFP_ATOMIC); - if (!m) - goto done; - m->ip_addr = iph->saddr; - memcpy(m->hw_addr, eh->h_source, ETH_ALEN); - m->used = jiffies; - - list_add(&m->node, &sc->mappings); - -done: - spin_unlock_irqrestore(&p->lock, flags); -} - -/* Perform SNAT modification on 'skb' and send out 'out_port'. If the - * port was not configured for SNAT, it will be sent through the interface - * unmodified. 'skb' is not consumed, so caller will need to free it. - */ -void -snat_skb(struct datapath *dp, const struct sk_buff *skb, int out_port, - gfp_t gfp) -{ - struct net_bridge_port *p = dp->ports[out_port]; - struct sk_buff *nskb; - - if (!p) - return; - - /* FIXME: Expensive. Just need to skb_clone() here? - * (However, the skb_copy() does linearize and ensure that the headers - * are accessible.) */ - nskb = skb_copy(skb, gfp); - if (!nskb) - return; - - nskb->dev = p->dev; - - /* We only SNAT IP, so just send it on its way if not */ - if (skb->protocol != htons(ETH_P_IP)) { - dp_xmit_skb(nskb); - return; - } - - /* Set the source MAC to the OF interface */ - memcpy(eth_hdr(nskb)->h_source, dp->ports[ODPP_LOCAL]->dev->dev_addr, ETH_ALEN); - - update_mapping(p, skb); - - /* Take the Ethernet header back off for netfilter hooks. */ - skb_pull(nskb, ETH_HLEN); - - NF_HOOK(PF_INET, NF_INET_FORWARD, nskb, skb->dev, nskb->dev, - snat_skb_finish); -} - -/* Remove SNAT configuration on port 'p'. - * - * NB: The caller must hold the port's spinlock. */ -int -snat_free_conf(struct net_bridge_port *p) -{ - struct snat_conf *sc = p->snat; - - if (!sc) - return -EINVAL; - - /* Free existing mapping entries */ - while (!list_empty(&sc->mappings)) { - struct snat_mapping *m = list_entry(sc->mappings.next, - struct snat_mapping, node); - list_del(&m->node); - kfree(m); - } - - kfree(p->snat); - p->snat = NULL; - - return 0; -} - -/* Remove SNAT configuration from an interface. */ -int snat_del_port(struct datapath *dp, int port) -{ - unsigned long flags; - struct net_bridge_port *p; - int error; - - if (port < 0 || port >= DP_MAX_PORTS) - return -EINVAL; - - p = dp->ports[port]; - if (!p) - return -ENOENT; - - spin_lock_irqsave(&p->lock, flags); - error = snat_free_conf(p); - spin_unlock_irqrestore(&p->lock, flags); - - return error; -} - -/* Add SNAT configuration to an interface. */ -int snat_add_port(struct datapath *dp, const struct odp_snat_config *osc) -{ - unsigned long flags; - struct net_bridge_port *p; - struct snat_conf *sc; - int mac_timeout; - - if (osc->port < 0 || osc->port >= DP_MAX_PORTS) - return -EINVAL; - - p = dp->ports[osc->port]; - if (!p) - return -ENOENT; - - mac_timeout = osc->mac_timeout; - if (!mac_timeout) - mac_timeout = MAC_TIMEOUT_DEFAULT; - - sc = kzalloc(sizeof *sc, GFP_KERNEL); - if (!sc) - return -ENOMEM; - - /* If SNAT is already configured on the port, check whether the same - * IP addresses are used. If so, just update the mac timeout - * configuration. Otherwise, drop all SNAT configuration and - * reconfigure it. */ - spin_lock_irqsave(&p->lock, flags); - if (p->snat) { - if (p->snat->ip_addr_start == ntohl(osc->ip_start) && - p->snat->ip_addr_end == ntohl(osc->ip_end)) { - p->snat->mac_timeout = mac_timeout; - spin_unlock_irqrestore(&p->lock, flags); - kfree(sc); - return 0; - } - - /* Free the existing configuration and mappings. */ - snat_free_conf(p); - } - - sc->ip_addr_start = ntohl(osc->ip_start); - sc->ip_addr_end = ntohl(osc->ip_end); - sc->mac_timeout = mac_timeout; - memcpy(sc->mac_addr, osc->mac_addr, ETH_ALEN); - INIT_LIST_HEAD(&sc->mappings); - - p->snat = sc; - spin_unlock_irqrestore(&p->lock, flags); - - return 0; -} -#endif diff --git a/datapath/snat.h b/datapath/snat.h deleted file mode 100644 index ca7f3525..00000000 --- a/datapath/snat.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifdef SUPPORT_SNAT -#ifndef ACT_SNAT_H -#define ACT_SNAT_H - -#include -#include -#include - -#include "datapath.h" - -void snat_internal_in(struct sk_buff *skb); -int snat_pre_route(struct sk_buff *skb); -void snat_skb(struct datapath *dp, const struct sk_buff *skb, int out_port, - gfp_t gfp); -void snat_save_header(struct sk_buff *skb); -int snat_copy_header(struct sk_buff *skb); -void snat_maint(struct net_bridge_port *p); -int snat_add_port(struct datapath *, const struct odp_snat_config *); -int snat_del_port(struct datapath *, int port); -int snat_free_conf(struct net_bridge_port *p); - -#endif -#endif diff --git a/debian/rules b/debian/rules index 695d61f4..707fe8b7 100755 --- a/debian/rules +++ b/debian/rules @@ -25,7 +25,7 @@ MA_DIR ?= /usr/share/modass # load default rules -include $(MA_DIR)/include/common-rules.make -DATAPATH_CONFIGURE_OPTS = --enable-snat +DATAPATH_CONFIGURE_OPTS = # Official build number. Leave set to 0 if not an official build. BUILD_NUMBER = 0 diff --git a/include/openflow/nicira-ext.h b/include/openflow/nicira-ext.h index 39f9bb10..176e0310 100644 --- a/include/openflow/nicira-ext.h +++ b/include/openflow/nicira-ext.h @@ -60,72 +60,11 @@ struct nicira_header { OFP_ASSERT(sizeof(struct nicira_header) == sizeof(struct ofp_vendor_header) + 4); -enum nx_snat_command { - NXSC_ADD, - NXSC_DELETE -}; - -/* Configuration for source-NATing */ -struct nx_snat_config { - uint8_t command; /* One of NXSC_*. */ - uint8_t pad[3]; - uint16_t port; /* Physical switch port. */ - uint16_t mac_timeout; /* Time to cache MAC addresses of SNAT'd hosts - in seconds. 0 uses the default value. */ - - /* Range of IP addresses to impersonate. Set both values to the - * same to support a single address. */ - uint32_t ip_addr_start; - uint32_t ip_addr_end; - - /* Range of transport ports that should be used as new source port. A - * value of zero, let's the switch choose.*/ - uint16_t tcp_start; - uint16_t tcp_end; - uint16_t udp_start; - uint16_t udp_end; - - /* MAC address to use for ARP requests for a SNAT IP address that - * comes in on a different interface than 'port'. A value of all - * zeros silently drops those ARP requests. Requests that arrive - * on 'port' get a response with the mac address of the datapath - * device. */ - uint8_t mac_addr[OFP_ETH_ALEN]; - uint8_t pad2[2]; -}; -OFP_ASSERT(sizeof(struct nx_snat_config) == 32); - -/* Action configuration. Not all actions require separate configuration. */ -struct nx_act_config { - struct nicira_header header; - uint16_t type; /* One of OFPAT_* */ - uint8_t pad[2]; - union { - struct nx_snat_config snat[0]; - }; /* Array of action configurations. The number - is inferred from the length field in the - header. */ -}; -OFP_ASSERT(sizeof(struct nx_act_config) == 20); - - enum nx_action_subtype { - NXAST_SNAT, /* Source-NAT */ + NXAST_SNAT__OBSOLETE, /* No longer used. */ NXAST_RESUBMIT /* Throw against flow table again. */ }; -/* Action structure for NXAST_SNAT. */ -struct nx_action_snat { - uint16_t type; /* OFPAT_VENDOR. */ - uint16_t len; /* Length is 8. */ - uint32_t vendor; /* NX_VENDOR_ID. */ - uint16_t subtype; /* NXAST_SNAT. */ - uint16_t port; /* Output port--it must be previously - configured. */ - uint8_t pad[4]; -}; -OFP_ASSERT(sizeof(struct nx_action_snat) == 16); - /* Action structure for NXAST_RESUBMIT. */ struct nx_action_resubmit { uint16_t type; /* OFPAT_VENDOR. */ diff --git a/include/openvswitch/datapath-protocol.h b/include/openvswitch/datapath-protocol.h index 3f2f71bd..20e24527 100644 --- a/include/openvswitch/datapath-protocol.h +++ b/include/openvswitch/datapath-protocol.h @@ -73,9 +73,6 @@ #define ODP_EXECUTE _IOR('O', 19, struct odp_execute) -#define ODP_SNAT_ADD_PORT _IOR('O', 20, struct odp_snat_config) -#define ODP_SNAT_DEL_PORT _IOR('O', 21, int) - struct odp_stats { /* Flows. */ __u32 n_flows; /* Number of flows in flow table. */ @@ -204,8 +201,7 @@ struct odp_flowvec { #define ODPAT_SET_NW_DST 9 /* IP destination address. */ #define ODPAT_SET_TP_SRC 10 /* TCP/UDP source port. */ #define ODPAT_SET_TP_DST 11 /* TCP/UDP destination port. */ -#define ODPAT_SNAT 12 /* Source NAT. */ -#define ODPAT_N_ACTIONS 13 +#define ODPAT_N_ACTIONS 12 struct odp_action_output { __u16 type; /* ODPAT_OUTPUT. */ @@ -265,13 +261,6 @@ struct odp_action_tp_port { __u16 reserved2; }; -struct odp_action_snat { - __u16 type; /* ODPAT_SNAT. */ - __u16 port; /* Output port. */ - __u16 reserved1; - __u16 reserved2; -}; - union odp_action { __u16 type; struct odp_action_output output; @@ -282,7 +271,6 @@ union odp_action { struct odp_action_dl_addr dl_addr; struct odp_action_nw_addr nw_addr; struct odp_action_tp_port tp_port; - struct odp_action_snat snat; }; struct odp_execute { @@ -313,28 +301,4 @@ struct odp_execute { */ #define ODP_VLAN_NONE 0xffff -/* Configuration for source-NATing */ -struct odp_snat_config { - __u16 port; - - /* Time to cache MAC addresses of SNAT'd hosts in seconds (0=default). */ - __u16 mac_timeout; - - /* Range of IP addresses to impersonate. Set both values to the same to - * support a single address. */ - __be32 ip_start, ip_end; - - /* Range of transport ports that should be used as new source port. A - * value of zero lets the kernel choose. */ - __be16 tcp_start, tcp_end; - __be16 udp_start, udp_end; - - /* MAC address to use for ARP requests for a SNAT IP address that comes in - * on a different interface than 'port'. A value of all zeros silently - * drops those ARP requests. Requests that arrive on 'port' get a response - * with the mac address of the datapath device. */ - __u8 mac_addr[ETH_ALEN]; - __u16 reserved; -}; - #endif /* openvswitch/datapath-protocol.h */ diff --git a/lib/dpif.c b/lib/dpif.c index f002f6ea..ba9b39f1 100644 --- a/lib/dpif.c +++ b/lib/dpif.c @@ -634,21 +634,6 @@ dpif_execute(struct dpif *dpif, uint16_t in_port, return error; } -int -dpif_snat_add_port(struct dpif *dpif, const struct odp_snat_config *osc) -{ - COVERAGE_INC(dpif_snat_add_port); - return do_ioctl(dpif, ODP_SNAT_ADD_PORT, "ODP_SNAT_ADD_PORT", osc); -} - -int -dpif_snat_del_port(struct dpif *dpif, uint16_t port) -{ - int tmp = port; - COVERAGE_INC(dpif_snat_del_port); - return do_ioctl(dpif, ODP_SNAT_DEL_PORT, "ODP_SNAT_DEL_PORT", &tmp); -} - int dpif_recv(struct dpif *dpif, struct ofpbuf **bufp) { diff --git a/lib/dpif.h b/lib/dpif.h index 8a4c6662..764ce406 100644 --- a/lib/dpif.h +++ b/lib/dpif.h @@ -97,9 +97,6 @@ int dpif_execute(struct dpif *, uint16_t in_port, const union odp_action[], size_t n_actions, const struct ofpbuf *); -int dpif_snat_add_port(struct dpif *, const struct odp_snat_config *); -int dpif_snat_del_port(struct dpif *, uint16_t port); - int dpif_recv(struct dpif *, struct ofpbuf **); void dpif_recv_wait(struct dpif *); diff --git a/lib/odp-util.c b/lib/odp-util.c index 9c2a57c3..0360892c 100644 --- a/lib/odp-util.c +++ b/lib/odp-util.c @@ -103,9 +103,6 @@ format_odp_action(struct ds *ds, const union odp_action *a) case ODPAT_SET_TP_DST: ds_put_format(ds, "set_tp_dst(%"PRIu16")", ntohs(a->tp_port.tp_port)); break; - case ODPAT_SNAT: - ds_put_format(ds, "snat(%"PRIu16")", a->snat.port); - break; default: ds_put_format(ds, "***bad action %"PRIu16"***", a->type); break; diff --git a/lib/ofp-print.c b/lib/ofp-print.c index 3b78feeb..a4611a2a 100644 --- a/lib/ofp-print.c +++ b/lib/ofp-print.c @@ -204,18 +204,6 @@ static void ofp_print_nx_action(struct ds *string, const struct nx_action_header *nah) { switch (ntohs(nah->subtype)) { - case NXAST_SNAT: { - const struct nx_action_snat *nas = (struct nx_action_snat *)nah; - uint16_t port = ntohs(nas->port); - - if (port < OFPP_MAX) { - ds_put_format(string, "nat:%"PRIu16, port); - } else { - ds_put_format(string, "nat:%"PRIu16" (invalid port)", port); - } - break; - } - case NXAST_RESUBMIT: { const struct nx_action_resubmit *nar = (struct nx_action_resubmit *)nah; ds_put_format(string, "resubmit:"); diff --git a/lib/vconn.c b/lib/vconn.c index ec1da4b4..6af44214 100644 --- a/lib/vconn.c +++ b/lib/vconn.c @@ -1218,7 +1218,6 @@ static int check_nicira_action(const union ofp_action *a, unsigned int len) { const struct nx_action_header *nah; - int error; if (len < 16) { VLOG_DBG_RL(&bad_ofmsg_rl, @@ -1228,12 +1227,6 @@ check_nicira_action(const union ofp_action *a, unsigned int len) nah = (const struct nx_action_header *) a; switch (ntohs(nah->subtype)) { - case NXAST_SNAT: - error = check_action_exact_len(a, len, 16); - if (error) { - return error; - } - return check_action_port(ntohs(((struct nx_action_snat *) nah)->port)); case NXAST_RESUBMIT: return check_action_exact_len(a, len, 16); default: diff --git a/lib/vlog-modules.def b/lib/vlog-modules.def index 4ef458ab..cbbb42ce 100644 --- a/lib/vlog-modules.def +++ b/lib/vlog-modules.def @@ -40,7 +40,6 @@ VLOG_MODULE(proc_net_compat) VLOG_MODULE(process) VLOG_MODULE(secchan) VLOG_MODULE(rconn) -VLOG_MODULE(snat) VLOG_MODULE(stp) VLOG_MODULE(stp_secchan) VLOG_MODULE(stats) diff --git a/m4/openvswitch.m4 b/m4/openvswitch.m4 index 88ed2a13..d5a7f29a 100644 --- a/m4/openvswitch.m4 +++ b/m4/openvswitch.m4 @@ -91,25 +91,6 @@ AC_DEFUN([OVS_CHECK_OPENSSL], AC_DEFINE([HAVE_OPENSSL], [1], [Define to 1 if OpenSSL is installed.]) fi]) -dnl Checks for --enable-snat and defines SUPPORT_SNAT if it is specified. -AC_DEFUN([OVS_CHECK_SNAT], - [AC_ARG_ENABLE( - [snat], - [AC_HELP_STRING([--enable-snat], - [Enable support for source-NAT action])], - [case "${enableval}" in - (yes) snat=true ;; - (no) snat=false ;; - (*) AC_MSG_ERROR([bad value ${enableval} for --enable-snat]) ;; - esac], - [snat=false]) - AM_CONDITIONAL([SUPPORT_SNAT], [test x$snat = xtrue]) - if test x$snat = xtrue; then - AC_DEFINE([SUPPORT_SNAT], [1], [Define to 1 if SNAT is desired.]) - SUPPORT_SNAT=-DSUPPORT_SNAT - AC_SUBST([SUPPORT_SNAT]) - fi]) - dnl Checks for libraries needed by lib/fault.c. AC_DEFUN([OVS_CHECK_FAULT_LIBS], [AC_CHECK_LIB([dl], [dladdr], [FAULT_LIBS=-ldl]) diff --git a/secchan/ofproto.c b/secchan/ofproto.c index 9cdf5d28..350f22e9 100644 --- a/secchan/ofproto.c +++ b/secchan/ofproto.c @@ -1971,19 +1971,11 @@ static void xlate_nicira_action(struct action_xlate_ctx *ctx, const struct nx_action_header *nah) { - const struct nx_action_snat *nas; const struct nx_action_resubmit *nar; int subtype = ntohs(nah->subtype); - union odp_action *oa; assert(nah->vendor == htonl(NX_VENDOR_ID)); switch (subtype) { - case NXAST_SNAT: - nas = (const struct nx_action_snat *) nah; - oa = odp_actions_add(ctx->out, ODPAT_SNAT); - oa->snat.port = ntohs(nas->port); - break; - case NXAST_RESUBMIT: nar = (const struct nx_action_resubmit *) nah; xlate_table_action(ctx, ofp_port_to_odp_port(ntohs(nar->in_port))); diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c index e5acffca..f97e07a8 100644 --- a/utilities/ovs-ofctl.c +++ b/utilities/ovs-ofctl.c @@ -220,10 +220,6 @@ usage(void) " dump-flows SWITCH FLOW print matching FLOWs\n" " dump-aggregate SWITCH print aggregate flow statistics\n" " dump-aggregate SWITCH FLOW print aggregate stats for FLOWs\n" -#ifdef SUPPORT_SNAT - " add-snat SWITCH IFACE IP add SNAT config to IFACE\n" - " del-snat SWITCH IFACE delete SNAT config on IFACE\n" -#endif " add-flow SWITCH FLOW add flow described by FLOW\n" " add-flows SWITCH FILE add flows from FILE\n" " mod-flows SWITCH FLOW modify actions of matching FLOWs\n" @@ -631,19 +627,6 @@ str_to_action(char *str, struct ofpbuf *b) ovs_fatal(0, "Drop actions must not be preceded by other " "actions"); } -#ifdef SUPPORT_SNAT - } else if (!strcasecmp(act, "nat")) { - struct nx_action_snat *sa; - - if (str_to_u32(arg) > OFPP_MAX) { - ovs_fatal(0, "Invalid nat port: %s\n", arg); - } - - sa = put_action(b, sizeof *sa, OFPAT_VENDOR); - sa->vendor = htonl(NX_VENDOR_ID); - sa->subtype = htons(NXAST_SNAT); - sa->port = htons(str_to_u32(arg)); -#endif } else if (!strcasecmp(act, "CONTROLLER")) { struct ofp_action_output *oao; oao = put_output_action(b, OFPP_CONTROLLER); @@ -863,60 +846,6 @@ do_dump_aggregate(const struct settings *s UNUSED, int argc, char *argv[]) dump_stats_transaction(argv[1], request); } -#ifdef SUPPORT_SNAT -static void -do_add_snat(const struct settings *s UNUSED, int argc UNUSED, char *argv[]) -{ - struct vconn *vconn; - struct ofpbuf *buffer; - struct nx_act_config *nac; - size_t size; - - /* Parse and send. */ - size = sizeof *nac + sizeof nac->snat[0]; - nac = make_openflow(size, OFPT_VENDOR, &buffer); - - nac->header.vendor = htonl(NX_VENDOR_ID); - nac->header.subtype = htonl(NXT_ACT_SET_CONFIG); - - nac->type = htons(NXAST_SNAT); - nac->snat[0].command = NXSC_ADD; - nac->snat[0].port = htons(str_to_u32(argv[2])); - nac->snat[0].mac_timeout = htons(0); - str_to_ip(argv[3], &nac->snat[0].ip_addr_start); - str_to_ip(argv[3], &nac->snat[0].ip_addr_end); - - open_vconn(argv[1], &vconn); - send_openflow_buffer(vconn, buffer); - vconn_close(vconn); -} - -static void -do_del_snat(const struct settings *s UNUSED, int argc UNUSED, char *argv[]) -{ - struct vconn *vconn; - struct ofpbuf *buffer; - struct nx_act_config *nac; - size_t size; - - /* Parse and send. */ - size = sizeof *nac + sizeof nac->snat[0]; - nac = make_openflow(size, OFPT_VENDOR, &buffer); - - nac->header.vendor = htonl(NX_VENDOR_ID); - nac->header.subtype = htonl(NXT_ACT_SET_CONFIG); - - nac->type = htons(NXAST_SNAT); - nac->snat[0].command = NXSC_DELETE; - nac->snat[0].port = htons(str_to_u32(argv[2])); - nac->snat[0].mac_timeout = htons(0); - - open_vconn(argv[1], &vconn); - send_openflow_buffer(vconn, buffer); - vconn_close(vconn); -} -#endif /* SUPPORT_SNAT */ - static void do_add_flow(const struct settings *s UNUSED, int argc UNUSED, char *argv[]) { @@ -1352,10 +1281,6 @@ static struct command all_commands[] = { { "dump-tables", 1, 1, do_dump_tables }, { "dump-flows", 1, 2, do_dump_flows }, { "dump-aggregate", 1, 2, do_dump_aggregate }, -#ifdef SUPPORT_SNAT - { "add-snat", 3, 3, do_add_snat }, - { "del-snat", 2, 2, do_del_snat }, -#endif { "add-flow", 2, 2, do_add_flow }, { "add-flows", 2, 2, do_add_flows }, { "mod-flows", 2, 2, do_mod_flows },