Skip to content

Commit

Permalink
Add per-customer translation algorithm
Browse files Browse the repository at this point in the history
This commit implements recommendations from the rfc 7422 
and the draft sunset4-nat64-port-allocation.
  • Loading branch information
dhfelix committed Jan 18, 2018
1 parent 9dfaf22 commit 7313c3b
Show file tree
Hide file tree
Showing 19 changed files with 1,274 additions and 50 deletions.
44 changes: 41 additions & 3 deletions include/nat64/common/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ enum config_mode {
MODE_JOOLD = (1 << 10),

MODE_INSTANCE = (1 << 11),
/** The current message is talking about customer pool. */
MODE_CUSTOMER = (1 << 12),
};

char *configmode_to_string(enum config_mode mode);
Expand All @@ -86,6 +88,7 @@ char *configmode_to_string(enum config_mode mode);
#define JOOLD_OPS (OP_ADVERTISE | OP_TEST)
#define LOGTIME_OPS (OP_DISPLAY)
#define INSTANCE_OPS (OP_ADD | OP_REMOVE)
#define CUSTOMER_OPS (OP_DISPLAY | OP_ADD | OP_REMOVE | OP_FLUSH )
/**
* @}
*/
Expand Down Expand Up @@ -131,15 +134,17 @@ enum parse_section {
SEC_EAMT = 32,
SEC_BLACKLIST = 64,
SEC_POOL6791 = 128,
SEC_INIT = 256
SEC_INIT = 256,
SEC_CUSTOMER = 512
};

/**
* @{
* Allowed modes for the operation mentioned in the name.
* eg. DISPLAY_MODES = Allowed modes for display operations.
*/
#define POOL_MODES (MODE_POOL6 | MODE_POOL4 | MODE_BLACKLIST | MODE_RFC6791)
#define POOL_MODES (MODE_POOL6 | MODE_POOL4 | MODE_BLACKLIST | MODE_RFC6791 \
| MODE_CUSTOMER)
#define TABLE_MODES (MODE_EAMT | MODE_BIB | MODE_SESSION)
#define ANY_MODE 0xFFFF

Expand All @@ -154,7 +159,7 @@ enum parse_section {
| MODE_EAMT | MODE_LOGTIME | MODE_PARSE_FILE | MODE_INSTANCE)
#define NAT64_MODES (MODE_GLOBAL | MODE_POOL6 | MODE_POOL4 | MODE_BIB \
| MODE_SESSION | MODE_LOGTIME | MODE_PARSE_FILE \
| MODE_INSTANCE | MODE_JOOLD)
| MODE_INSTANCE | MODE_JOOLD | MODE_CUSTOMER)
/**
* @}
*/
Expand Down Expand Up @@ -320,6 +325,39 @@ union request_eamt {
} flush;
};

struct customer_entry_usr {
struct ipv6_prefix prefix6;
__u8 groups6_size_len;
struct ipv4_prefix prefix4;
__u8 ports_division_len;
struct port_range ports;
};

/**
* Configuration for the "customer" module.
*/
union request_customer {
struct {
/* Nothing needed here. */
} display;
struct customer_entry_usr add;
struct {
/**
* Whether the BIB and the sessions tables should also be
* cleared (false) or not (true).
*/
config_bool quick;
} rm;
struct {
/**
* Whether the BIB and the sessions tables should also be
* cleared (false) or not (true).
*/
config_bool quick;
} flush;
};


/**
* Configuration for the "Log time" module.
*/
Expand Down
9 changes: 9 additions & 0 deletions include/nat64/mod/common/nl/customer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#ifndef __NL_CUSTOMER_H__
#define __NL_CUSTOMER_H__

#include <net/genetlink.h>
#include "nat64/mod/common/xlator.h"

int handle_customer_config(struct xlator *jool, struct genl_info *info);

#endif
79 changes: 79 additions & 0 deletions include/nat64/mod/stateful/pool4/customer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#ifndef __JOOL_MOD_POOL4_CUSTOMER_H_
#define __JOOL_MOD_POOL4_CUSTOMER_H_

#include <linux/net.h>
#include "nat64/mod/common/types.h"
#include "nat64/mod/common/config.h"

struct customer_table {
/** IPv6 addresses that use this customer table. */
struct ipv6_prefix prefix6;
/** Number of bits of 'prefix6' which represent the subnetwork. */
__u8 groups6_size_len;

/** Pool4 for this table. */
struct ipv4_prefix prefix4;
/** Hop size that divide the ports range for every IPv6 subnetwork
* in CIDR format. */
__u8 ports_division_len;

struct port_range ports;

/** Port range size "ports" in CIDR format, for bitwise operations. */
unsigned short ports_size_len;
};


bool customer_table_contains(struct customer_table *table, struct in6_addr *src6);

/**
* Obtain the total count of ports from this customer.
* (i.e. IPv4 prefix count * port range count )
*/
__u32 customer_table_get_total_ports_size(struct customer_table *table);

/**
* Indicates which IPv6 group the address belongs to.
*/
__u16 customer_table_get_group_by_addr(struct customer_table *table,
struct in6_addr *src6);

/**
* Indicates the available port size for each IPv6 group.
*/
__u32 customer_table_get_group_ports_size(struct customer_table *table);

/**
* Number of contiguous ports to be used as requested by the user
* for each IPv6 group.
*/
__u16 customer_table_get_port_range_hop(struct customer_table *table);

/**
* Initial port number for the IPv6 group 'group',
* you can add an offset so that the initial port is different for each
* network request.
*/
__u32 customer_get_group_first_port(struct customer_table *table,
unsigned int offset, __u16 group, __u16 port_hop);

/**
* Ports hope size for the following range of available ports for an IPv6 group.
*/
__u32 customer_table_get_group_ports_hop(struct customer_table *table);

/**
* Number of IPv6 addresses for each IPv6 group.
*/
__u32 customer_table_get_group_size(struct customer_table *table);

/**
* Same as the port_range_count(ports) but
* for bitwise operations (1 << port_mask).
*
* @return port_mask
*/
unsigned short customer_table_get_ports_mask(struct customer_table *table);

void customer_table_put(struct customer_table *customer);
#endif /* __JOOL_MOD_POOL4_CUSTOMER_H_ */
9 changes: 9 additions & 0 deletions include/nat64/mod/stateful/pool4/db.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "nat64/mod/common/types.h"
#include "nat64/mod/common/config.h"
#include "nat64/mod/common/route.h"
#include "nat64/mod/stateful/pool4/customer.h"

struct pool4;

Expand All @@ -30,6 +31,13 @@ int pool4db_rm(struct pool4 *pool, const __u32 mark, enum l4_protocol proto,
int pool4db_rm_usr(struct pool4 *pool, struct pool4_entry_usr *entry);
void pool4db_flush(struct pool4 *pool);

int customerdb_foreach(struct pool4 *pool,
int (*cb)(struct customer_table *, void *), void *arg);
int customerdb_add(struct pool4 *pool, const struct customer_entry_usr *entry);
void customerdb_flush(struct pool4 *pool, struct ipv4_range *range_removed,
int *error);
int customerdb_rm(struct pool4 *pool, struct ipv4_range *range_removed);

/*
* Read functions (Legal to use anywhere)
*/
Expand All @@ -50,6 +58,7 @@ int mask_domain_next(struct mask_domain *masks,
bool *consecutive);
bool mask_domain_matches(struct mask_domain *masks,
struct ipv4_transport_addr *addr);
bool mask_domain_is_customer(struct mask_domain *masks);
bool mask_domain_is_dynamic(struct mask_domain *masks);
__u32 mask_domain_get_mark(struct mask_domain *masks);

Expand Down
1 change: 1 addition & 0 deletions include/nat64/usr/argp/options.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ enum argp_flags {
ARGP_GLOBAL = 'g',
ARGP_PARSE_FILE = 'p',
ARGP_INSTANCE = 7001,
ARGP_CUSTOMER = 7003,

/* Operations */
ARGP_DISPLAY = 'd',
Expand Down
12 changes: 12 additions & 0 deletions include/nat64/usr/customer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#ifndef _JOOL_USR_CUSTOMER_H
#define _JOOL_USR_CUSTOMER_H

#include "nat64/common/config.h"
#include "nat64/usr/types.h"

int customer_display(display_flags flags);
int customer_add(struct customer_entry_usr *entry);
int customer_rm(bool quick);
int customer_flush(bool quick);

#endif /* _JOOL_USR_CUSTOMER_H */
1 change: 1 addition & 0 deletions include/nat64/usr/global.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#define OPTNAME_GLOBAL "global"
#define OPTNAME_POOL6 "pool6"
#define OPTNAME_POOL4 "pool4"
#define OPTNAME_CUSTOMER "customer"
#define OPTNAME_BLACKLIST "blacklist"
#define OPTNAME_RFC6791 "pool6791"
#define OPTNAME_EAMT "eamt"
Expand Down
3 changes: 3 additions & 0 deletions include/nat64/usr/str_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ int str_to_addr6_port(const char *str, struct ipv6_transport_addr *out);
int str_to_prefix6(const char *str, struct ipv6_prefix *out);
int str_to_prefix4(const char *str, struct ipv4_prefix *out);

int str_to_customer_prefix6(const char *str, struct ipv6_prefix *prefix_out, __u8 *group_size_len);
int str_to_customer_prefix4(const char *str, struct ipv4_prefix *prefix_out, __u8 *port_len);

/**
* Prints the @millis amount of milliseconds as spreadsheet-friendly format in
* the console.
Expand Down
117 changes: 117 additions & 0 deletions mod/common/nl/customer.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
#include "nat64/mod/common/nl/customer.h"

#include "nat64/mod/common/nl/nl_common.h"
#include "nat64/mod/common/nl/nl_core2.h"
#include "nat64/mod/stateful/pool4/customer.h"
#include "nat64/mod/stateful/pool4/db.h"
#include "nat64/mod/stateful/bib/db.h"

static int customer_table_to_usr(struct customer_table *table, void *arg)
{
return nlbuffer_write(arg, table, sizeof(*table));
}

static int handle_customer_display(struct pool4 *pool, struct genl_info *info,
union request_customer *request)
{
struct nlcore_buffer buffer;
int error = 0;

log_debug("Sending customer table to userspace.");

error = nlbuffer_init_response(&buffer, info, nlbuffer_response_max_size());
if (error)
return nlcore_respond(info, error);

error = customerdb_foreach(pool, customer_table_to_usr, &buffer);
nlbuffer_set_pending_data(&buffer, error > 0);
error = (error >= 0)
? nlbuffer_send(info, &buffer)
: nlcore_respond(info, error);

nlbuffer_free(&buffer);
return error;
}

static int handle_customer_add(struct pool4 *pool, struct genl_info *info,
union request_customer *request)
{
if (verify_superpriv())
return nlcore_respond(info, -EPERM);

log_debug("Adding elements to customer table.");
return nlcore_respond(info, customerdb_add(pool, &request->add));
}

static int handle_customer_rm(struct xlator *jool, struct genl_info *info,
union request_customer *request)
{
struct ipv4_range range;
int error;

if (verify_superpriv())
return nlcore_respond(info, -EPERM);

log_debug("Removing elements from customer table.");

error = customerdb_rm(jool->nat64.pool4, &range);

if (!error && xlat_is_nat64() && !request->rm.quick) {

This comment has been minimized.

Copy link
@ydahhrk

ydahhrk Jan 18, 2018

Member

Stateness was already validated in handle_customer_config(); no need to do it again

bib_rm_range(jool->nat64.bib, L4PROTO_TCP, &range);
bib_rm_range(jool->nat64.bib, L4PROTO_ICMP, &range);
bib_rm_range(jool->nat64.bib, L4PROTO_UDP, &range);
}

return nlcore_respond(info, error);
}

static int handle_customer_flush(struct xlator *jool, struct genl_info *info,
union request_customer *request)
{
struct ipv4_range range;
int error;

if (verify_superpriv())
return nlcore_respond(info, -EPERM);

log_debug("Flushing customer table.");

customerdb_flush(jool->nat64.pool4, &range, &error);
if (!error && xlat_is_nat64() && !request->flush.quick) {
bib_rm_range(jool->nat64.bib, L4PROTO_TCP, &range);
bib_rm_range(jool->nat64.bib, L4PROTO_ICMP, &range);
bib_rm_range(jool->nat64.bib, L4PROTO_UDP, &range);
}

return nlcore_respond(info, 0);

This comment has been minimized.

Copy link
@ydahhrk

ydahhrk Jan 18, 2018

Member

No need for this code either

This comment has been minimized.

Copy link
@ydahhrk

ydahhrk Jan 18, 2018

Member

Not returning error code in nlcore_respond()?

}

int handle_customer_config(struct xlator *jool, struct genl_info *info)
{
struct request_hdr *hdr = get_jool_hdr(info);
union request_customer *request = (union request_customer *)(hdr + 1);
int error;

if (xlat_is_siit()) {
log_err("SIIT doesn't have customer.");
return nlcore_respond(info, -EINVAL);
}

error = validate_request_size(info, sizeof(*request));
if (error)
return nlcore_respond(info, error);

switch (be16_to_cpu(hdr->operation)) {
case OP_DISPLAY:
return handle_customer_display(jool->nat64.pool4, info, request);
case OP_ADD:
return handle_customer_add(jool->nat64.pool4, info, request);
case OP_REMOVE:
return handle_customer_rm(jool, info, request);
case OP_FLUSH:
return handle_customer_flush(jool, info, request);
}

log_err("Unknown operation: %u", be16_to_cpu(hdr->operation));
return nlcore_respond(info, -EINVAL);
}
3 changes: 3 additions & 0 deletions mod/common/nl/nl_handler2.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "nat64/mod/common/nl/pool4.h"
#include "nat64/mod/common/nl/pool6.h"
#include "nat64/mod/common/nl/session.h"
#include "nat64/mod/common/nl/customer.h"

static struct genl_multicast_group mc_groups[1] = {
{
Expand Down Expand Up @@ -118,6 +119,8 @@ static int multiplex_request(struct xlator *jool, struct genl_info *info)
return handle_joold_request(jool, info);
case MODE_INSTANCE:
return handle_instance_request(info);
case MODE_CUSTOMER:
return handle_customer_config(jool, info);
}

log_err("Unknown configuration mode: %d", be16_to_cpu(hdr->mode));
Expand Down
2 changes: 2 additions & 0 deletions mod/stateful/Kbuild
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,10 @@ jool_common += ../common/nl/nl_common.o
jool_common += ../common/nl/pool4.o
jool_common += ../common/nl/pool6.o
jool_common += ../common/nl/session.o
jool_common += ../common/nl/customer.o

jool += pool4/empty.o
jool += pool4/customer.o
jool += pool4/db.o
jool += pool4/rfc6056.o

Expand Down
Loading

1 comment on commit 7313c3b

@dhfelix
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Please sign in to comment.