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

[UPG-NAT] Controlled CG-NAT #122

Merged
merged 7 commits into from
Jun 8, 2021
Merged

[UPG-NAT] Controlled CG-NAT #122

merged 7 commits into from
Jun 8, 2021

Conversation

sergeymatov
Copy link
Contributor

In order to allow UPG perform CG-NAT function following changes has been introduced:
To UPG:

  • Ability to allocate and manage NAT Pools
  • UE IP Address pool information IE to communicate NAT Pools to SMC
  • BBF PFCP IEs to manage NAT Pool lookup and applying NAT to given UE IP
  • UPG can manage NAT bindings configured for VPP NAT plugin

To NAT plugin:

  • NAT bindings allocation/deletion mechanics exposed to UPG
  • Binding lookup via bihash
  • Override ED-NAT slow-path address and port allocation in respect to NAT binding created for given user address

upf/pfcp.c Outdated
Comment on lines 4770 to 4774
length -= 2;

if (length < 2)
return PFCP_CAUSE_INVALID_LENGTH;

Copy link
Member

Choose a reason for hiding this comment

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

teh length check is already covered by line 4766

Copy link
Contributor Author

Choose a reason for hiding this comment

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

removed

upf/pfcp.c Outdated
pfcp_bbf_up_function_features_t *n =
va_arg (*args, pfcp_bbf_up_function_features_t *);

s = format (s, "NAT:%u", (*n & BBF_UP_NAT));
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
s = format (s, "NAT:%u", (*n & BBF_UP_NAT));
s = format (s, "NAT:%u", !!(*n & BBF_UP_NAT));

upf/pfcp.c Outdated
{
u64 *v = p;

if (length % 2 != 0 || length < 2)
Copy link
Member

Choose a reason for hiding this comment

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

minimum length of this IE is 4 bytes

Copy link
Contributor Author

Choose a reason for hiding this comment

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

check line updated

upf/pfcp.c Outdated
Comment on lines 4824 to 4825
put_u16_little (*vec, *v);
put_u16_little (*vec, *v >> 16);
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
put_u16_little (*vec, *v);
put_u16_little (*vec, *v >> 16);
put_u32_little (*vec, *v);

Copy link
Contributor Author

Choose a reason for hiding this comment

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

oh, missed this. thanks

upf/pfcp.c Outdated
Comment on lines 6208 to 6211
if (ISSET_BIT(*v, IP_VERSION_4))
s = format (s, "IPv4");
else
s = format (s, "IPv6");
Copy link
Member

Choose a reason for hiding this comment

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

both flags can be set (v4 and v6)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed

upf/upf_pfcp.c Show resolved Hide resolved
upf/upf_pfcp_api.c Show resolved Hide resolved
{
if (!(vec_is_equal (np->network_instance, ue_p->nwi_name)))
continue;
pfcp_bbf_nat_port_block_t *block;
Copy link
Member

Choose a reason for hiding this comment

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

local variable definition should not follow code

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

Copy link
Member

Choose a reason for hiding this comment

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

this has not been addressed

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sorry, missed this here but fixed for stable branch.

upf/upf_pfcp_api.c Show resolved Hide resolved
Comment on lines 765 to 789
do
{
err =
upf_nat_create_binding (user_ip, addr->ext_addr, port_start, port_end,
np->vrf_id);
if (!err)
{
addr->used_blocks += 1;
sx->nat_addr = addr;
created_binding->block = vec_dup (np->name);
created_binding->outside_addr.as_u32 = addr->ext_addr.as_u32;
created_binding->port_range.start_port = port_start;
created_binding->port_range.end_port = port_end;
SET_BIT (created_binding->grp.fields,
TP_CREATED_BINDING_NAT_PORT_BLOCK);
SET_BIT (created_binding->grp.fields,
TP_CREATED_BINDING_NAT_OUTSIDE_ADDRESS);
SET_BIT (created_binding->grp.fields,
TP_CREATED_BINDING_NAT_EXTERNAL_PORT_RANGE);
return 0;
}
port_start += np->port_block_size;
port_end = port_start + np->port_block_size;
}
while (port_end < np->max_port);
Copy link
Member

Choose a reason for hiding this comment

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

I hate this trial and error approach to finding a suitable block

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've removed this try-err thing out from UPG code and make logic for finding port block inside NAT code.
NAT plugin in full of such constructions in terms of port selection. Now its a part of binding validation procedure.

Copy link
Contributor

@ivan4th ivan4th left a comment

Choose a reason for hiding this comment

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

The major problem I see is the lack of any tests (integration or e2e), but sadly this will have to wait for now.
Other than that, one of the problems I found looks a potential bug, others being some nitpicking

upf/upf_pfcp_api.c Outdated Show resolved Hide resolved
upf/upf_pfcp.c Outdated

ASSERT (ap->used_blocks > 0);

ap->used_blocks -= 1;
Copy link
Contributor

Choose a reason for hiding this comment

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

--

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed

upf/upf_pfcp.c Outdated Show resolved Hide resolved
@@ -359,7 +367,6 @@ def associate(self):
IE_NodeId(id_type="FQDN", id="ergw")
]), PFCPAssociationSetupResponse)
self.assertEqual(CauseValues[resp[IE_Cause].cause], "Request accepted")
self.assertIn(b"vpp", resp[IE_EnterpriseSpecific].data)
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this change somehow related to this PR? This is actually a problem (#104), as the build id should contain upg not vpp, but I thought of fixing it separately and not by removing this check, but rather by fixing the id itself and replacing vpp with upg here

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In general, association setup response checks should be enhanced with:

  • proper build ID check
  • BBF UserPlane Features checks
    I think it's worth a separate review

@ivan4th
Copy link
Contributor

ivan4th commented May 28, 2021

LGTM

upf/upf.c Outdated
Comment on lines 108 to 110
np = pool_elt_at_index (gtm->nat_pools, p[0]);

return np;
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
np = pool_elt_at_index (gtm->nat_pools, p[0]);
return np;
return pool_elt_at_index (gtm->nat_pools, p[0]);

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

upf/upf.c Outdated
{
u32 i = 0;

vec_reset_length (np->addresses);
Copy link
Member

Choose a reason for hiding this comment

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

to avoid unnecessary fragmentation, you could used vec_validate to make sure the vector is large enough to hold all entries before going into the loop.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

upf/upf_cli.c Outdated
{
.path = "upf nat pool",
.short_help =
"upf nat pool nwi <nwi-name> start <ip4-addr> end <ip4-addr> min_port <min-port> max_port <max-port> block_size <port-block-size> vrf <vrf-id> name <name> [del]",
Copy link
Member

Choose a reason for hiding this comment

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

A NWI currently uniquely identifies a VRF, it the extra VRF really needed or different from the NWI VRF?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We are operating nwi name w/o nwi lookup itself. I will add TODO in a code, but removing vrf out will create a cascade of changes to charts.

Copy link
Member

Choose a reason for hiding this comment

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

"because something somewhere else would need to be redone" is not an argument for leaving this code in a inconsistent state. A TODO for this is only acceptable if it is followed up with some urgency.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

VRF removed as redundant CLI argument

{
if (!(vec_is_equal (np->network_instance, ue_p->nwi_name)))
continue;
pfcp_bbf_nat_port_block_t *block;
Copy link
Member

Choose a reason for hiding this comment

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

this has not been addressed

Sergey Matov added 4 commits June 2, 2021 14:27
NAT plugin dedicated changes. ED NAT address and port
selection done based on bindings created by UPG plugin.
Fixed PFCP IE ordering for BBF/TP messages.
Fixed minor issues in UPG NAT processing.
Also populate Reencode PFCP test .txt files with missing
TP IEs.
@ivan4th
Copy link
Contributor

ivan4th commented Jun 2, 2021

LGTM from my side

Copy link
Member

@RoadRunnr RoadRunnr left a comment

Choose a reason for hiding this comment

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

I think the CLI (nwi vs. vrf) should be sorted out before this is merged to master

upf/upf.c Outdated
return VNET_API_ERROR_NO_SUCH_ENTRY;

nat_pool = pool_elt_at_index (gtm->nat_pools, p[0]);
//TBD: nat pool cleanup upf_delete_nat_addresses(nat_pool);
Copy link
Member

Choose a reason for hiding this comment

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

removing a NAT pool that used entries would crash at some, right?

upf/upf_cli.c Outdated
{
.path = "upf nat pool",
.short_help =
"upf nat pool nwi <nwi-name> start <ip4-addr> end <ip4-addr> min_port <min-port> max_port <max-port> block_size <port-block-size> vrf <vrf-id> name <name> [del]",
Copy link
Member

Choose a reason for hiding this comment

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

"because something somewhere else would need to be redone" is not an argument for leaving this code in a inconsistent state. A TODO for this is only acceptable if it is followed up with some urgency.

@sergeymatov sergeymatov force-pushed the exp/cg-nat branch 4 times, most recently from d81f68c to 169da0c Compare June 6, 2021 03:48
upf/upf_cli.c Outdated
// something like this). To avoid this, two strings could be picked
// in single unformat call. Probably Address Sanitaizer should be
// used to identify problems with unformatting input line
else if (unformat (line_input, "nwi %_%v%_ name %_%v%_", &nwi_s, &name))
Copy link
Member

Choose a reason for hiding this comment

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

it seems that "%s" does not suffer from this problem. It would therefore be possible to scan the names as string and then convert them to vectors.
That would IMHO be a better workaround.

Copy link
Member

Choose a reason for hiding this comment

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

Looking at the full function also makes me wonder if the fact that name is not initialized to zero might play a role in the problem.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Initiation of name vectors to 0 resolves the issue, so I've removed W/A.
Thanks for good notice

Changes:
- Remove redundant vrf_id from "upf nat pool" cli from code and
  upf scapy tests.
- Free nat addresses vector on nat pool deletion.
- Code optimization and cleanup.
@ivan4th ivan4th added the enhancement New feature or request label Jun 8, 2021
@sergeymatov sergeymatov merged commit 7ac1fcb into master Jun 8, 2021
@sergeymatov sergeymatov deleted the exp/cg-nat branch June 8, 2021 11:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants