diff options
author | Pravin B Shelar <pshelar@nicira.com> | 2014-11-11 11:53:47 -0800 |
---|---|---|
committer | Pravin B Shelar <pshelar@nicira.com> | 2014-11-12 15:08:33 -0800 |
commit | a36de779d739cdcd72c65c67a547a786798b595a (patch) | |
tree | 736331a0c51ec85f22fe982b18135d7f9d9131ca /ofproto/tunnel.c | |
parent | 0746a84f3916193c0704e94a4c214f672c5c542e (diff) | |
download | openvswitch-a36de779d739cdcd72c65c67a547a786798b595a.tar.gz |
openvswitch: Userspace tunneling.
Following patch adds support for userspace tunneling. Tunneling
needs three more component first is routing table which is configured by
caching kernel routes and second is ARP cache which build automatically
by snooping arp. And third is tunnel protocol table which list all
listening protocols which is populated by vswitchd as tunnel ports
are added. GRE and VXLAN protocol support is added in this patch.
Tunneling works as follows:
On packet receive vswitchd check if this packet is targeted to tunnel
port. If it is then vswitchd inserts tunnel pop action which pops
header and sends packet to tunnel port.
On packet xmit rather than generating Set tunnel action it generate
tunnel push action which has tunnel header data. datapath can use
tunnel-push action data to generate header for each packet and
forward this packet to output port. Since tunnel-push action
contains most of packet header vswitchd needs to lookup routing
table and arp table to build this action.
Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
Acked-by: Thomas Graf <tgraf@noironetworks.com>
Acked-by: Ben Pfaff <blp@nicira.com>
Diffstat (limited to 'ofproto/tunnel.c')
-rw-r--r-- | ofproto/tunnel.c | 73 |
1 files changed, 67 insertions, 6 deletions
diff --git a/ofproto/tunnel.c b/ofproto/tunnel.c index 4be539021..25df9eb2e 100644 --- a/ofproto/tunnel.c +++ b/ofproto/tunnel.c @@ -19,18 +19,26 @@ #include "byte-order.h" #include "connectivity.h" +#include "csum.h" +#include "dpif.h" #include "dynamic-string.h" #include "fat-rwlock.h" #include "hash.h" #include "hmap.h" #include "netdev.h" #include "odp-util.h" +#include "ofpbuf.h" #include "packets.h" +#include "route-table.h" #include "seq.h" #include "smap.h" #include "socket-util.h" +#include "tnl-arp-cache.h" +#include "tnl-ports.h" #include "tunnel.h" #include "vlog.h" +#include "unaligned.h" +#include "ofproto-dpif.h" VLOG_DEFINE_THIS_MODULE(tunnel); @@ -136,7 +144,7 @@ ofproto_tunnel_init(void) static bool tnl_port_add__(const struct ofport_dpif *ofport, const struct netdev *netdev, - odp_port_t odp_port, bool warn) + odp_port_t odp_port, bool warn, bool native_tnl, const char name[]) OVS_REQ_WRLOCK(rwlock) { const struct netdev_tunnel_config *cfg; @@ -185,6 +193,11 @@ tnl_port_add__(const struct ofport_dpif *ofport, const struct netdev *netdev, } hmap_insert(*map, &tnl_port->match_node, tnl_hash(&tnl_port->match)); tnl_port_mod_log(tnl_port, "adding"); + + if (native_tnl) { + tnl_port_map_insert(odp_port, tnl_port->match.ip_dst, + cfg->dst_port, name); + } return true; } @@ -193,10 +206,10 @@ tnl_port_add__(const struct ofport_dpif *ofport, const struct netdev *netdev, * tunnel. */ void tnl_port_add(const struct ofport_dpif *ofport, const struct netdev *netdev, - odp_port_t odp_port) OVS_EXCLUDED(rwlock) + odp_port_t odp_port, bool native_tnl, const char name[]) OVS_EXCLUDED(rwlock) { fat_rwlock_wrlock(&rwlock); - tnl_port_add__(ofport, netdev, odp_port, true); + tnl_port_add__(ofport, netdev, odp_port, true, native_tnl, name); fat_rwlock_unlock(&rwlock); } @@ -206,7 +219,8 @@ tnl_port_add(const struct ofport_dpif *ofport, const struct netdev *netdev, * tnl_port_add(). */ bool tnl_port_reconfigure(const struct ofport_dpif *ofport, - const struct netdev *netdev, odp_port_t odp_port) + const struct netdev *netdev, odp_port_t odp_port, + bool native_tnl, const char name[]) OVS_EXCLUDED(rwlock) { struct tnl_port *tnl_port; @@ -215,13 +229,13 @@ tnl_port_reconfigure(const struct ofport_dpif *ofport, fat_rwlock_wrlock(&rwlock); tnl_port = tnl_find_ofport(ofport); if (!tnl_port) { - changed = tnl_port_add__(ofport, netdev, odp_port, false); + changed = tnl_port_add__(ofport, netdev, odp_port, false, native_tnl, name); } else if (tnl_port->netdev != netdev || tnl_port->match.odp_port != odp_port || tnl_port->change_seq != seq_read(connectivity_seq_get())) { VLOG_DBG("reconfiguring %s", tnl_port_get_name(tnl_port)); tnl_port_del__(ofport); - tnl_port_add__(ofport, netdev, odp_port, true); + tnl_port_add__(ofport, netdev, odp_port, true, native_tnl, name); changed = true; } fat_rwlock_unlock(&rwlock); @@ -239,8 +253,11 @@ tnl_port_del__(const struct ofport_dpif *ofport) OVS_REQ_WRLOCK(rwlock) tnl_port = tnl_find_ofport(ofport); if (tnl_port) { + const struct netdev_tunnel_config *cfg = + netdev_get_tunnel_config(tnl_port->netdev); struct hmap **map; + tnl_port_map_delete(tnl_port->match.ip_dst, cfg->dst_port); tnl_port_mod_log(tnl_port, "removing"); map = tnl_match_map(&tnl_port->match); hmap_remove(*map, &tnl_port->match_node); @@ -651,3 +668,47 @@ tnl_port_get_name(const struct tnl_port *tnl_port) OVS_REQ_RDLOCK(rwlock) { return netdev_get_name(tnl_port->netdev); } + +int +tnl_port_build_header(const struct ofport_dpif *ofport, + const struct flow *tnl_flow, + uint8_t dmac[ETH_ADDR_LEN], + uint8_t smac[ETH_ADDR_LEN], + ovs_be32 ip_src, struct ovs_action_push_tnl *data) +{ + struct tnl_port *tnl_port; + struct eth_header *eth; + struct ip_header *ip; + void *l3; + int res; + + fat_rwlock_rdlock(&rwlock); + tnl_port = tnl_find_ofport(ofport); + ovs_assert(tnl_port); + + /* Build Ethernet and IP headers. */ + memset(data->header, 0, sizeof data->header); + + eth = (struct eth_header *)data->header; + memcpy(eth->eth_dst, dmac, ETH_ADDR_LEN); + memcpy(eth->eth_src, smac, ETH_ADDR_LEN); + eth->eth_type = htons(ETH_TYPE_IP); + + l3 = (eth + 1); + ip = (struct ip_header *) l3; + + ip->ip_ihl_ver = IP_IHL_VER(5, 4); + ip->ip_tos = tnl_flow->tunnel.ip_tos; + ip->ip_ttl = tnl_flow->tunnel.ip_ttl; + ip->ip_frag_off = (tnl_flow->tunnel.flags & FLOW_TNL_F_DONT_FRAGMENT) ? + htons(IP_DF) : 0; + + put_16aligned_be32(&ip->ip_src, ip_src); + put_16aligned_be32(&ip->ip_dst, tnl_flow->tunnel.ip_dst); + + res = netdev_build_header(tnl_port->netdev, data); + ip->ip_csum = csum(ip, sizeof *ip); + fat_rwlock_unlock(&rwlock); + + return res; +} |