Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions include/dp_lpm.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,13 @@ const struct dp_port *dp_get_ip4_out_port(const struct dp_port *in_port,
uint32_t t_vni,
const struct dp_flow *df,
struct dp_iface_route *route,
uint32_t *p_ip);
bool *is_default_route);

const struct dp_port *dp_get_ip6_out_port(const struct dp_port *in_port,
uint32_t t_vni,
const struct dp_flow *df,
struct dp_iface_route *route,
union dp_ipv6 *p_ipv6);
bool *is_default_route);
uint32_t dp_get_gw_ip4(void);
const union dp_ipv6 *dp_get_gw_ip6(void);

Expand Down
18 changes: 12 additions & 6 deletions src/dp_lpm.c
Original file line number Diff line number Diff line change
Expand Up @@ -278,13 +278,14 @@ const struct dp_port *dp_get_ip4_out_port(const struct dp_port *in_port,
uint32_t t_vni,
const struct dp_flow *df,
struct dp_iface_route *route,
uint32_t *p_ip)
bool *is_default_route)
{
uint32_t dst_ip = ntohl(df->dst.dst_addr);
struct rte_rib_node *node;
struct rte_rib *root;
uint64_t next_hop;
struct dp_port *dst_port;
uint8_t route_depth;

if (t_vni == 0)
t_vni = in_port->iface.vni;
Expand All @@ -307,23 +308,26 @@ const struct dp_port *dp_get_ip4_out_port(const struct dp_port *in_port,
if (dst_port->is_pf)
rte_memcpy(route, rte_rib_get_ext(node), sizeof(*route));

if (DP_FAILED(rte_rib_get_ip(node, p_ip)))
if (DP_FAILED(rte_rib_get_depth(node, &route_depth)))
return NULL;

// Normally we should match prefix/length, but for length 0 the ip is implied
*is_default_route = route_depth == 0;

return dst_port;
}

const struct dp_port *dp_get_ip6_out_port(const struct dp_port *in_port,
uint32_t t_vni,
const struct dp_flow *df,
struct dp_iface_route *route,
union dp_ipv6 *p_ipv6)
bool *is_default_route)
{
struct rte_rib6_node *node;
struct rte_rib6 *root;
uint64_t next_hop;
struct dp_port *dst_port;
struct rte_ipv6_addr ip;
uint8_t route_depth;

if (t_vni == 0)
t_vni = in_port->iface.vni;
Expand All @@ -346,9 +350,11 @@ const struct dp_port *dp_get_ip6_out_port(const struct dp_port *in_port,
if (dst_port->is_pf)
rte_memcpy(route, rte_rib6_get_ext(node), sizeof(*route));

if (DP_FAILED(rte_rib6_get_ip(node, &ip)))
if (DP_FAILED(rte_rib6_get_depth(node, &route_depth)))
return NULL;

dp_ipv6_from_rte(p_ipv6, &ip);
// Normally we should match prefix/length, but for length 0 the ip is implied
*is_default_route = route_depth == 0;

return dst_port;
}
6 changes: 3 additions & 3 deletions src/nodes/ipv4_lookup_node.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@ static __rte_always_inline rte_edge_t get_next_index(__rte_unused struct rte_nod
{
struct dp_flow *df = dp_get_flow_ptr(m);
struct dp_iface_route route;
uint32_t ip = 0;
bool is_default_route;
const struct dp_port *in_port = dp_get_in_port(m);
const struct dp_port *out_port;

// TODO: add broadcast routes when machine is added
if (df->l4_type == IPPROTO_UDP && df->l4_info.trans_port.dst_port == htons(DP_BOOTP_SRV_PORT))
return IPV4_LOOKUP_NEXT_DHCP;

out_port = dp_get_ip4_out_port(in_port, df->tun_info.dst_vni, df, &route, &ip);
out_port = dp_get_ip4_out_port(in_port, df->tun_info.dst_vni, df, &route, &is_default_route);
if (!out_port)
return IPV4_LOOKUP_NEXT_DROP;

Expand All @@ -53,7 +53,7 @@ static __rte_always_inline rte_edge_t get_next_index(__rte_unused struct rte_nod
if (!in_port->is_pf)
df->tun_info.dst_vni = route.vni;

df->flow_type = ip == 0 ? DP_FLOW_SOUTH_NORTH : DP_FLOW_WEST_EAST;
df->flow_type = is_default_route ? DP_FLOW_SOUTH_NORTH : DP_FLOW_WEST_EAST;
df->nxt_hop = out_port->port_id; // always valid since coming from struct dp_port

return IPV4_LOOKUP_NEXT_NAT;
Expand Down
6 changes: 3 additions & 3 deletions src/nodes/ipv6_lookup_node.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ static __rte_always_inline rte_edge_t get_next_index(__rte_unused struct rte_nod
struct dp_flow *df = dp_get_flow_ptr(m);
struct rte_ether_hdr *ether_hdr = rte_pktmbuf_mtod(m, struct rte_ether_hdr *);
struct dp_iface_route route;
bool is_default_route;
const struct dp_port *in_port = dp_get_in_port(m);
const struct dp_port *out_port;
union dp_ipv6 ip;
int t_vni;

t_vni = in_port->is_pf ? df->tun_info.dst_vni : 0;

out_port = dp_get_ip6_out_port(in_port, t_vni, df, &route, &ip);
out_port = dp_get_ip6_out_port(in_port, t_vni, df, &route, &is_default_route);
if (!out_port)
return IPV6_LOOKUP_NEXT_DROP;

Expand All @@ -47,7 +47,7 @@ static __rte_always_inline rte_edge_t get_next_index(__rte_unused struct rte_nod
if (!in_port->is_pf)
df->tun_info.dst_vni = route.vni;

df->flow_type = dp_is_ipv6_zero(&ip) ? DP_FLOW_SOUTH_NORTH : DP_FLOW_WEST_EAST;
df->flow_type = is_default_route ? DP_FLOW_SOUTH_NORTH : DP_FLOW_WEST_EAST;
df->nxt_hop = out_port->port_id; // always valid since coming from struct dp_port

return IPV6_LOOKUP_NEXT_SNAT;
Expand Down
2 changes: 2 additions & 0 deletions test/local/grpc_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ def _call(self, args):
or (isinstance(error, GrpcError) and expectFailure)):
return None
raise error
elif expectedError:
raise AssertionError(f"Error {expectedError} expected, none received")
return response

def _getSpec(self, args):
Expand Down
39 changes: 39 additions & 0 deletions test/local/test_nat.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,51 @@
# SPDX-FileCopyrightText: 2023 SAP SE or an SAP affiliate company and IronCore contributors
# SPDX-License-Identifier: Apache-2.0

import ipaddress
import pytest
import threading

from helpers import *


def vm_sender(dst_ip):
pkt = (Ether(dst=PF0.mac, src=VM1.mac) /
IP(dst=dst_ip, src=VM1.ip) /
UDP(dport=1234))
delayed_sendp(pkt, VM1.tap)

def try_ip_range(grpc_client, iprange):
net = ipaddress.ip_network(iprange, strict=False)
route = str(net)
grpc_client.addroute(vni1, route, vni1, neigh_vni1_ul_ipv6)

if int(net.network_address) > 0:
threading.Thread(target=vm_sender, args=(str(net.network_address-1),)).start()
pkt = sniff_packet(PF0.tap, is_udp_pkt)
assert pkt[IP].src != VM1.ip, \
"IP not translated"

threading.Thread(target=vm_sender, args=(str(net.network_address),)).start()
pkt = sniff_packet(PF0.tap, is_udp_pkt)
assert pkt[IP].src == VM1.ip, \
"IP translated instead of staying local"

if int(net.broadcast_address) < 2**32 - 1:
# Need to use +2 to get around conntrack remembering it from another range
threading.Thread(target=vm_sender, args=(str(net.broadcast_address+2),)).start()
pkt = sniff_packet(PF0.tap, is_udp_pkt)
assert pkt[IP].src != VM1.ip, \
"IP not translated"

grpc_client.delroute(vni1, route)

def test_nat_default_route(prepare_ifaces, grpc_client):
nat_ul_ipv6 = grpc_client.addnat(VM1.name, nat_vip, nat_local_min_port, nat_local_max_port)
try_ip_range(grpc_client, "128.0.0.0/1")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice idea to test with X.0.0.0/1 for checking the default route behaviour with /0.

try_ip_range(grpc_client, "0.0.0.0/1")
grpc_client.delnat(VM1.name)


def test_network_nat_external_icmp_echo(prepare_ipv4, grpc_client):
nat_ul_ipv6 = grpc_client.addnat(VM1.name, nat_vip, nat_local_min_port, nat_local_max_port)
external_ping(nat_vip, nat_ul_ipv6)
Expand Down
3 changes: 3 additions & 0 deletions test/local/test_zzz_grpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,9 @@ def test_grpc_route(prepare_ifaces, grpc_client):
grpc_client.addinterface(VM4.name, VM4.pci, 999, VM4.ip, VM4.ipv6)
grpc_client.addroute(999, "1.2.3.4/24", vni1, neigh_vni1_ul_ipv6)
grpc_client.expect_error(301).addroute(999, "1.2.3.4/24", vni1, neigh_vni1_ul_ipv6)
grpc_client.expect_error(301).addroute(999, "1.2.3.255/24", vni1, neigh_vni1_ul_ipv6)
grpc_client.addroute(999, "1.2.3.4/25", vni1, neigh_vni1_ul_ipv6)
grpc_client.delroute(999, "1.2.3.4/25")
grpc_client.delroute(999, "1.2.3.4/24")
grpc_client.expect_error(302).delroute(999, "1.2.3.4/24")
grpc_client.addroute(999, "1.2.3.4/24", vni1, neigh_vni1_ul_ipv6)
Expand Down
Loading