summaryrefslogtreecommitdiff
path: root/ofproto/tunnel.c
diff options
context:
space:
mode:
Diffstat (limited to 'ofproto/tunnel.c')
-rw-r--r--ofproto/tunnel.c73
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;
+}