Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add listing of all nat entries to gRPC protocol #638

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
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
11 changes: 5 additions & 6 deletions cli/dpservice-cli/cmd/list_nats.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,17 +53,16 @@ type ListNatsOptions struct {
}

func (o *ListNatsOptions) AddFlags(fs *pflag.FlagSet) {
flag.AddrVar(fs, &o.NatIP, "nat-ip", o.NatIP, "NAT IP to get info for")
defaultAddr, err := netip.ParseAddr("0.0.0.0")
if err != nil {
defaultAddr = o.NatIP
}
flag.AddrVar(fs, &o.NatIP, "nat-ip", defaultAddr, "NAT IP to get info for")
fs.StringVar(&o.NatType, "nat-type", "0", "NAT type: Any = 0/Local = 1/Neigh(bor) = 2")
fs.StringVar(&o.SortBy, "sort-by", "", "Column to sort by.")
}

func (o *ListNatsOptions) MarkRequiredFlags(cmd *cobra.Command) error {
for _, name := range []string{"nat-ip"} {
if err := cmd.MarkFlagRequired(name); err != nil {
return err
}
}
return nil
}

Expand Down
6 changes: 3 additions & 3 deletions cli/dpservice-cli/renderer/renderer.go
Original file line number Diff line number Diff line change
Expand Up @@ -335,10 +335,10 @@ func (t defaultTableConverter) natTable(nats []api.Nat) (*TableData, error) {
var headers []any
// if command was get nat or there are no nats
if len(nats) > 0 && nats[0].InterfaceID != "" {
headers = []any{"InterfaceID", "IP", "MinPort", "MaxPort", "UnderlayRoute"}
headers = []any{"InterfaceID", "NatIP", "MinPort", "MaxPort", "UnderlayRoute"}
// if command was list nats
} else {
headers = []any{"VNI", "IP", "MinPort", "MaxPort", "UnderlayRoute", "NatType"}
headers = []any{"VNI", "IP", "MinPort", "MaxPort", "UnderlayRoute", "NatIP", "NatType"}
}

columns := make([][]any, len(nats))
Expand All @@ -348,7 +348,7 @@ func (t defaultTableConverter) natTable(nats []api.Nat) (*TableData, error) {
columns[i] = []any{nat.NatMeta.InterfaceID, nat.Spec.NatIP, nat.Spec.MinPort, nat.Spec.MaxPort, nat.Spec.UnderlayRoute}
// if command was list nats
} else {
columns[i] = []any{nat.Spec.Vni, nat.Spec.NatIP, nat.Spec.MinPort, nat.Spec.MaxPort, nat.Spec.UnderlayRoute}
columns[i] = []any{nat.Spec.Vni, nat.Spec.NatIP, nat.Spec.MinPort, nat.Spec.MaxPort, nat.Spec.UnderlayRoute, nat.Spec.ActualNatIP}
if len(nats) > 0 && nats[i].Spec.UnderlayRoute == nil {
columns[i] = append(columns[i], "Local")
} else {
Expand Down
1 change: 1 addition & 0 deletions go/dpservice-go/api/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,7 @@ type NatSpec struct {
MaxPort uint32 `json:"max_port"`
UnderlayRoute *netip.Addr `json:"underlay_route,omitempty"`
Vni uint32 `json:"vni"`
ActualNatIP *netip.Addr `json:"actual_nat_ip,omitempty"`
}

type NatList struct {
Expand Down
18 changes: 12 additions & 6 deletions go/dpservice-go/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -802,24 +802,30 @@ func (c *client) ListNats(ctx context.Context, natIP *netip.Addr, natType string
var nats = make([]api.Nat, len(natEntries))
var nat api.Nat
for i, natEntry := range natEntries {

var underlayRoute, vipIP netip.Addr
var underlayRoute, natIP, nattedIP netip.Addr
if natEntry.GetUnderlayRoute() != nil {
underlayRoute, err = netip.ParseAddr(string(natEntry.GetUnderlayRoute()))
if err != nil {
return nil, fmt.Errorf("error parsing underlay route: %w", err)
}
nat.Spec.UnderlayRoute = &underlayRoute
nat.Spec.NatIP = nil
nat.Spec.NatIP = nil // "natted" IP, i.e. local NIC IP is not applicable for neighnats
nat.Kind = api.NeighborNatKind
} else if natEntry.GetNatIp() != nil {
vipIP, err = netip.ParseAddr(string(natEntry.GetNatIp().GetAddress()))
nattedIP, err = netip.ParseAddr(string(natEntry.GetNatIp().GetAddress()))
if err != nil {
return nil, fmt.Errorf("error parsing nat ip: %w", err)
return nil, fmt.Errorf("error parsing natted ip: %w", err)
}
nat.Spec.NatIP = &vipIP
nat.Spec.NatIP = &nattedIP
nat.Kind = api.NatKind
}
if natEntry.GetActualNatIp() != nil {
natIP, err = netip.ParseAddr(string(natEntry.GetActualNatIp().GetAddress()))
if err != nil {
return nil, fmt.Errorf("error parsing nat ip: %w", err)
}
nat.Spec.ActualNatIP = &natIP
}
nat.Spec.MinPort = natEntry.MinPort
nat.Spec.MaxPort = natEntry.MaxPort
nat.Spec.Vni = natEntry.Vni
Expand Down
393 changes: 203 additions & 190 deletions go/dpservice-go/proto/dpdk.pb.go

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion go/dpservice-go/proto/generated_from.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v0.3.5-69-g07d470f
v0.3.14-5-g54be192
1 change: 1 addition & 0 deletions include/grpc/dp_grpc_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ struct dpgrpc_nat {
uint32_t vni; // neighnat or reply only
union dp_ipv6 neigh_addr6; // neighnat only
union dp_ipv6 ul_addr6; // reply only
struct dp_ip_address natted_ip; // list localnats reply only
};

struct dpgrpc_lb_port {
Expand Down
3 changes: 2 additions & 1 deletion proto/dpdk.proto
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,12 @@ message LbPort {
}

message NatEntry {
IpAddress nat_ip = 1;
IpAddress nat_ip = 1; // TODO This is actually the local "natted" IP
uint32 min_port = 2;
uint32 max_port = 3;
bytes underlay_route = 4;
uint32 vni = 5;
IpAddress actual_nat_ip = 6; // The actual NAT IP
}

message Route {
Expand Down
9 changes: 6 additions & 3 deletions src/dp_nat.c
Original file line number Diff line number Diff line change
Expand Up @@ -783,14 +783,16 @@ int dp_list_nat_local_entries(uint32_t nat_ip, struct dp_grpc_responder *respond
if (DP_FAILED(ret))
return DP_GRPC_ERR_ITERATOR;

if (data->nat_ip == nat_ip) {
// VIP entries use the same table and have data->nat_ip set to 0 so they would match when nat_ip is 0
if (data->nat_ip != 0 && (nat_ip == 0 || data->nat_ip == nat_ip)) {
reply = dp_grpc_add_reply(responder);
if (!reply)
return DP_GRPC_ERR_OUT_OF_MEMORY;
reply->min_port = data->nat_port_range[0];
reply->max_port = data->nat_port_range[1];
dp_set_ipaddr4(&reply->addr, nkey->ip);
dp_set_ipaddr4(&reply->natted_ip, nkey->ip);
reply->vni = nkey->vni;
dp_set_ipaddr4(&reply->addr, data->nat_ip);
}
}
return DP_GRPC_OK;
Expand All @@ -804,14 +806,15 @@ int dp_list_nat_neigh_entries(uint32_t nat_ip, struct dp_grpc_responder *respond
dp_grpc_set_multireply(responder, sizeof(*reply));

TAILQ_FOREACH(current, &nat_headp, entries) {
if (current->nat_ip == nat_ip) {
if (nat_ip == 0 || current->nat_ip == nat_ip) {
reply = dp_grpc_add_reply(responder);
if (!reply)
return DP_GRPC_ERR_OUT_OF_MEMORY;
reply->min_port = current->port_range[0];
reply->max_port = current->port_range[1];
reply->vni = current->vni;
dp_copy_ipv6(&reply->ul_addr6, &current->dst_ipv6);
dp_set_ipaddr4(&reply->addr, current->nat_ip);
}
}
return DP_GRPC_OK;
Expand Down
16 changes: 12 additions & 4 deletions src/grpc/dp_async_grpc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -588,16 +588,20 @@ void ListLocalNatsCall::ParseReply(struct dpgrpc_reply* reply)
{
struct dpgrpc_nat *nat;
NatEntry *nat_entry;
IpAddress *natted_ip;
IpAddress *nat_ip;

FOREACH_MESSAGE(nat, reply) {
nat_entry = reply_.add_nat_entries();
nat_ip = new IpAddress();
GrpcConv::DpToGrpcAddress(&nat->addr, nat_ip);
nat_entry->set_allocated_nat_ip(nat_ip);
natted_ip = new IpAddress();
GrpcConv::DpToGrpcAddress(&nat->natted_ip, natted_ip);
nat_entry->set_allocated_nat_ip(natted_ip);
nat_entry->set_min_port(nat->min_port);
nat_entry->set_max_port(nat->max_port);
nat_entry->set_vni(nat->vni);
nat_ip = new IpAddress();
GrpcConv::DpToGrpcAddress(&nat->addr, nat_ip);
nat_entry->set_allocated_actual_nat_ip(nat_ip);
}
}

Expand Down Expand Up @@ -655,7 +659,7 @@ void DeleteNeighborNatCall::ParseReply(__rte_unused struct dpgrpc_reply* reply)

const char* ListNeighborNatsCall::FillRequest(struct dpgrpc_request* request)
{
DPGRPC_LOG_INFO("Getting NAT info",
DPGRPC_LOG_INFO("Listing neighbor Nats",
DP_LOG_IPV4STR(request_.nat_ip().address().c_str()));
if (!GrpcConv::GrpcToDpAddress(request_.nat_ip(), &request->list_localnat))
return "Invalid nat_ip";
Expand All @@ -665,6 +669,7 @@ void ListNeighborNatsCall::ParseReply(struct dpgrpc_reply* reply)
{
struct dpgrpc_nat *nat;
NatEntry *nat_entry;
IpAddress *nat_ip;
char strbuf[INET6_ADDRSTRLEN];

FOREACH_MESSAGE(nat, reply) {
Expand All @@ -674,6 +679,9 @@ void ListNeighborNatsCall::ParseReply(struct dpgrpc_reply* reply)
nat_entry->set_min_port(nat->min_port);
nat_entry->set_max_port(nat->max_port);
nat_entry->set_vni(nat->vni);
nat_ip = new IpAddress();
GrpcConv::DpToGrpcAddress(&nat->addr, nat_ip);
nat_entry->set_allocated_actual_nat_ip(nat_ip);
}
}

Expand Down
2 changes: 1 addition & 1 deletion test/local/test_nat.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def test_network_nat_pkt_relay(prepare_ifaces, grpc_client):
assert spec == localspec, \
"Failed to add NAT properly"

neighspec = { 'underlay_route': neigh_vni1_ul_ipv6, 'min_port': nat_neigh_min_port, 'max_port': nat_neigh_max_port, 'vni': vni1 }
neighspec = { 'underlay_route': neigh_vni1_ul_ipv6, 'min_port': nat_neigh_min_port, 'max_port': nat_neigh_max_port, 'vni': vni1, 'actual_nat_ip': nat_vip }
specs = grpc_client.listneighnats(nat_vip)
assert specs == [neighspec], \
"Invalid neighboring NAT list"
Expand Down
8 changes: 4 additions & 4 deletions test/local/test_zzz_grpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,8 +194,8 @@ def test_grpc_nat_list(prepare_ifaces, grpc_client):
grpc_client.addnat(VM1.name, nat_vip, nat_local_min_port, nat_local_max_port)
grpc_client.addnat(VM2.name, nat_vip, nat_local_max_port, nat_local_max_port+1)
# Local NAT list is not a list of NAT objects, need to create it manually
nat1spec = { "nat_ip": VM1.ip, "min_port": nat_local_min_port, "max_port": nat_local_max_port, "vni": VM1.vni }
nat2spec = { "nat_ip": VM2.ip, "min_port": nat_local_max_port, "max_port": nat_local_max_port+1, "vni": VM1.vni }
nat1spec = { "nat_ip": VM1.ip, "min_port": nat_local_min_port, "max_port": nat_local_max_port, "vni": VM1.vni, "actual_nat_ip": nat_vip }
nat2spec = { "nat_ip": VM2.ip, "min_port": nat_local_max_port, "max_port": nat_local_max_port+1, "vni": VM1.vni, "actual_nat_ip": nat_vip }
specs = grpc_client.listlocalnats(nat_vip)
# List order is apparently not the same as the order of operations
assert specs == [ nat2spec, nat1spec ], \
Expand Down Expand Up @@ -251,8 +251,8 @@ def test_grpc_neighnat_list(prepare_ifaces, grpc_client):
grpc_client.addneighnat(nat_vip, vni1, nat_neigh_min_port, nat_neigh_max_port, neigh_vni1_ul_ipv6)
grpc_client.addneighnat(nat_vip, vni1, nat_neigh_max_port, nat_neigh_max_port+1, neigh_vni1_ul_ipv6)
# Neighbor NAT list is not a list of NAT objects, need to create it manually
neigh1spec = { "min_port": nat_neigh_min_port, "max_port": nat_neigh_max_port, "underlay_route": neigh_vni1_ul_ipv6, "vni": vni1 }
neigh2spec = { "min_port": nat_neigh_max_port, "max_port": nat_neigh_max_port+1, "underlay_route": neigh_vni1_ul_ipv6, "vni": vni1 }
neigh1spec = { "min_port": nat_neigh_min_port, "max_port": nat_neigh_max_port, "underlay_route": neigh_vni1_ul_ipv6, "vni": vni1, "actual_nat_ip": nat_vip }
neigh2spec = { "min_port": nat_neigh_max_port, "max_port": nat_neigh_max_port+1, "underlay_route": neigh_vni1_ul_ipv6, "vni": vni1, "actual_nat_ip": nat_vip }
specs = grpc_client.listneighnats(nat_vip)
assert specs == [ neigh1spec, neigh2spec ], \
"Neighboring NATs not properly added to a list"
Expand Down
Loading