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

Topics/enhancements #41

Merged
merged 5 commits into from
Apr 23, 2020
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 0 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ RUN wget -qO bess.zip https://github.com/NetSys/bess/archive/${BESS_COMMIT}.zip
WORKDIR bess-${BESS_COMMIT}
COPY core/modules/ core/modules/
COPY core/utils/ core/utils/
COPY protobuf/ protobuf/
COPY patches/bess patches
RUN cp -a ${DPDK_DIR} deps/dpdk-19.11.1 && \
cat patches/* | patch -p1
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ reading from file /tmp/tmpUBTGau, link-type EN10MB (Ethernet)
* Dynamic IP routing
* Support for IPv4 datagrams reassembly
* Support for IP packets fragmentation
* Support for UE IP NAT

### In Progress

Expand Down
120 changes: 102 additions & 18 deletions conf/spgwu.bess
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,28 @@ from conf.utils import *
conf_file = get_env('CONF_FILE', 'conf/spgwu.json')
conf = get_json_conf(conf_file, False)

# Maximum number of flows to manage ip frags for re-assembly
# Maximum number of flows to manage ip4 frags for re-assembly
max_ip_defrag_flows = None
try:
max_ip_defrag_flows = int(conf["max_ip_defrag_flows"])
except ValueError:
print('Invalid value for max_ip_defrag_flows. Not installing IPDefrag module.')
print('Invalid value for max_ip_defrag_flows. Not installing IP4Defrag module.')
except KeyError:
print('max_ip_defrag_flows value not set. Not installing IPDefrag module.')
print('max_ip_defrag_flows value not set. Not installing IP4Defrag module.')

# Enable ip4 fragmentation
ip_frag_with_eth_mtu = None
try:
ip_frag_with_eth_mtu = int(conf["ip_frag_with_eth_mtu"])
except ValueError:
print('Invalid value for ip_frag_with_eth_mtu. Not installing IP4Frag module.')
except KeyError:
print('ip_frag_with_eth_mtu value not set. Not installing IP4Frag module.')
ajamshed marked this conversation as resolved.
Show resolved Hide resolved

# See this link for details:
## https://github.com/NetSys/bess/blob/master/bessctl/module_tests/timestamp.py
measure = bool(conf["measure"])


# ====================================================
# Port Helpers
Expand Down Expand Up @@ -57,14 +71,16 @@ def scan_dpdk_ports():


class Port:
def __init__(self, name):
def __init__(self, name, ext_addrs):
self.name = name
self.wid = None
self.fpi = None
self.fpo = None
self.bpf = None
self.bpfgate = 0
self.routes_table = None
self.nat = None
self.ext_addrs = ext_addrs

def bpf_gate(self):
if self.bpfgate < MAX_GATES - 2:
Expand Down Expand Up @@ -95,11 +111,11 @@ class Port:
self.bpf = __bess_module__("{}FastBPF".format(name), 'BPF')
self.bpf.clear()

# Reassemble IP4 fragments (if needed)
defrag = __bess_module__("{}IP4Defrag".format(name), 'IPDefrag', num_flows=max_ip_defrag_flows, numa=0)
# Default drop when no matches
self.fpi -> defrag:1 -> self.bpf:0 -> Sink()
defrag:0 -> Sink()
if measure:
self.fpi -> Timestamp() -> self.bpf:0 -> Sink()
else:
self.fpi -> self.bpf:0 -> Sink()

# Initialize route module
self.rtr = __bess_module__("{}Routes".format(name), 'IPLookup')
Expand Down Expand Up @@ -172,9 +188,40 @@ class Port:

# Direct fast path traffic to Frag module
merge = __bess_module__("{}Merge".format(name), 'Merge')
frag = __bess_module__("{}IP4Frag".format(name), 'IPFrag')
merge -> frag:1 -> self.fpo
frag:0 -> Sink()

out = self.fpo

ajamshed marked this conversation as resolved.
Show resolved Hide resolved
# Attach frag module (if enabled)
if ip_frag_with_eth_mtu is not None:
frag = __bess_module__("{}IP4Frag".format(name), 'IPFrag', mtu=ip_frag_with_eth_mtu)
frag:1 -> out
frag:0 -> Sink()
out = frag

# Attach telemeric module (if enabled)
if measure:
m = Measure()
m -> out
out = m

# Attach nat module (if enabled)
if self.ext_addrs is not None:
# Tokenize the string
addrs = self.ext_addrs.split(' or ')
# Make a list of ext_addr
nat_list = list()
for addr in addrs:
nat_dict = dict()
nat_dict['ext_addr'] = addr
nat_list.append(nat_dict)

# Create the NAT module
self.nat = __bess_module__("{}NAT".format(conf[interface]["ifname"]), 'NAT', ext_addrs=nat_list)
self.nat:1 -> out
out = self.nat

# Attach Merge module to the 'outlist' of modules
merge -> out

tc = 'slow{}'.format(wid)
try:
Expand Down Expand Up @@ -235,8 +282,14 @@ for wid in xrange(workers):

interfaces = ["s1u", "sgi"]
ports = {}

for idx, interface in enumerate(interfaces):
port = Port(conf[interface]["ifname"])
try:
ext_addrs = conf[interface]["ip_masquerade"]
except KeyError:
ext_addrs = None

port = Port(conf[interface]["ifname"], ext_addrs)
if port.name in ports:
continue
port.setup_port(idx, workers)
Expand All @@ -245,6 +298,7 @@ for idx, interface in enumerate(interfaces):
s1u_ifname = conf["s1u"]["ifname"]
sgi_ifname = conf["sgi"]["ifname"]


# ====================================================
# Downlink Pipeline
# ====================================================
Expand All @@ -260,12 +314,31 @@ except ValueError:
# Setting filter to detect UE subnet
sgiFastBPF = ports[sgi_ifname].bpf
UEGate = ports[sgi_ifname].bpf_gate()
ue_filter = {"priority": -UEGate,
"filter": "ip dst net {}".format(ue_cidr), "gate": UEGate}
if ports[sgi_ifname].nat is not None:
ue_filter = {"priority": -UEGate,
"filter": "ip dst {}".format(ports[sgi_ifname].ext_addrs), "gate": UEGate}
else:
ue_filter = {"priority": -UEGate,
"filter": "ip dst net {}".format(ue_cidr), "gate": UEGate}
sgiFastBPF.add(filters=[ue_filter])

sgiFastBPF:UEGate \
-> EtherTrim::GenericDecap(bytes=14) \
_in = sgiFastBPF
gate = UEGate
# Append nat module (if enabled)
if ports[sgi_ifname].nat is not None:
_in:gate -> 1:ports[sgi_ifname].nat
_in = ports[sgi_ifname].nat
gate = 0

# Append sgiIP4Defrag module (if enabled)
if max_ip_defrag_flows is not None:
_in:gate -> sgiIP4Defrag::IPDefrag(num_flows=max_ip_defrag_flows, numa=0)
_in = sgiIP4Defrag
gate = 1
# Drop pkts that are unable to be fragmented
sgiIP4Defrag:0 -> Sink()

_in:gate -> EtherTrim::GenericDecap(bytes=14) \
-> GTPUEncap::GtpuEncap(s1u_sgw_ip=ip2long(ips_by_interface(s1u_ifname)[0]), num_subscribers=max_sessions):1 \
-> S1UEtherAdd::GenericEncap(fields=[
{'size': 6, 'value': {'value_int': 0x0}},
Expand All @@ -278,6 +351,8 @@ sgiFastBPF:UEGate \
# Drop unknown packets
GTPUEncap:0 -> Sink()



# ====================================================
# Uplink Pipeline
# ====================================================
Expand Down Expand Up @@ -310,8 +385,15 @@ s1uFastBPF.add(filters=[uplink_filter])

sgiRoutes = ports[sgi_ifname].rtr

s1uFastBPF:GTPUGate \
-> EtherDecapTrim::GenericDecap(bytes=14) -> GTPUDecap::GtpuDecap(ename="GTPUEncap"):1 \
# Append s1uIP4Defrag module (if enabled)
if max_ip_defrag_flows is not None:
s1uFastBPF:GTPUGate -> s1uIP4Defrag::IPDefrag(num_flows=max_ip_defrag_flows, numa=0):1 -> EtherDecapTrim::GenericDecap(bytes=14)
# Drop pkts that are unable to be fragmented
s1uIP4Defrag:0 -> Sink()
else:
s1uFastBPF:GTPUGate -> EtherDecapTrim::GenericDecap(bytes=14)

EtherDecapTrim -> GTPUDecap::GtpuDecap(ename="GTPUEncap"):1 \
-> SGIEtherAdd::GenericEncap(fields=[
{'size': 6, 'value': {'value_int': 0x0}},
{'size': 6, 'value': {'value_int': mac2hex(mac_by_interface(sgi_ifname))}},
Expand All @@ -327,6 +409,8 @@ s1uFastBPF:GTPUEchoGate \
GTPUEcho:0 -> Sink()
GTPUDecap:0 -> Sink()



# ====================================================
# SIM_TEST
# ====================================================
Expand Down
16 changes: 12 additions & 4 deletions conf/spgwu.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,24 @@
"": "max UE sessions",
"max_sessions": 50000,

"": "max IP frag table entries (for IPv4 reassembly)",
"max_ip_defrag_flows": 1000,
"": "max IP frag table entries (for IPv4 reassembly). Update the line below to `\"max_ip_defrag_flows\": 1000` to enable",
"": "max_ip_defrag_flows: 1000",

"": "Gateway interfaces",
"": "Update the line below to `\"ip_frag_with_eth_mtu\": 1518` to enable",
"": "ip_frag_with_eth_mtu: 1518",

"": "Telemetrics-See this link for details: https://github.com/NetSys/bess/blob/master/bessctl/module_tests/timestamp.py",
"measure": false,

"": "Gateway interfaces",
"s1u": {
"ifname": "ens803f2"
},

"": "UE IP Natting. Update the line below to `\"ip_masquerade\": \"<ip> [or <ip>]\"` to enable",
"sgi": {
"ifname": "ens803f3"
"ifname": "ens803f3",
"": "ip_masquerade: 18.0.0.1 or 18.0.0.2 or 18.0.0.3"
ajamshed marked this conversation as resolved.
Show resolved Hide resolved
},

"": "Number of worker threads. Default: use 1 thread to run both (uplink/downlink) pipelines",
Expand Down
6 changes: 6 additions & 0 deletions core/modules/gtpu_decap.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
#include "utils/udp.h"
/* for gtp header */
#include "utils/gtp.h"
/* for GetDesc() */
#include "utils/format.h"
#include <rte_jhash.h>
/*----------------------------------------------------------------------------------*/
using bess::utils::be32_t;
Expand Down Expand Up @@ -96,4 +98,8 @@ CommandResponse GtpuDecap::Init(const bess::pb::GtpuDecapArg &arg) {
return CommandSuccess();
}
/*----------------------------------------------------------------------------------*/
std::string GtpuDecap::GetDesc() const {
return bess::utils::Format("%zu sessions", (size_t)rte_hash_count(session_map));
}
/*----------------------------------------------------------------------------------*/
ADD_MODULE(GtpuDecap, "gtpu_decap", "first version of gtpu decap module")
2 changes: 2 additions & 0 deletions core/modules/gtpu_decap.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ class GtpuDecap final : public Module {

CommandResponse Init(const bess::pb::GtpuDecapArg &arg);
void ProcessBatch(Context *ctx, bess::PacketBatch *batch) override;
// returns the number of active UE sessions
std::string GetDesc() const override;

private:
struct rte_hash *session_map = NULL;
Expand Down
17 changes: 17 additions & 0 deletions core/modules/gtpu_encap.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
#include "utils/udp.h"
/* for gtp header */
#include "utils/gtp.h"
/* for GetDesc() */
#include "utils/format.h"
#include <rte_jhash.h>
/*----------------------------------------------------------------------------------*/
using bess::utils::be16_t;
Expand All @@ -33,6 +35,8 @@ const Commands GtpuEncap::cmds = {
{"remove", "GtpuEncapRemoveSessionRecordArg",
MODULE_CMD_FUNC(&GtpuEncap::RemoveSessionRecord), Command::THREAD_SAFE},
{"show_records", "EmptyArg", MODULE_CMD_FUNC(&GtpuEncap::ShowRecords),
Command::THREAD_SAFE},
{"show_count", "EmptyArg", MODULE_CMD_FUNC(&GtpuEncap::ShowCount),
Command::THREAD_SAFE}};
/*----------------------------------------------------------------------------------*/
// Template for generating UDP packets without data
Expand Down Expand Up @@ -152,6 +156,7 @@ CommandResponse GtpuEncap::AddSessionRecord(
<< ToIpv4Address(be32_t(ueaddr)) << std::endl;
return CommandFailure(ENOMEM, "Failed to insert session record");
}

return CommandSuccess();
}
/*----------------------------------------------------------------------------------*/
Expand Down Expand Up @@ -202,6 +207,14 @@ CommandResponse GtpuEncap::ShowRecords(const bess::pb::EmptyArg &) {
return CommandSuccess();
}
/*----------------------------------------------------------------------------------*/
CommandResponse GtpuEncap::ShowCount(const bess::pb::EmptyArg &) {
bess::pb::GtpuEncapArg arg;
arg.set_s1u_sgw_ip(0);
arg.set_num_subscribers(rte_hash_count(session_map));
DLOG(INFO) << "# of records: " << rte_hash_count(session_map) << std::endl;
return CommandSuccess(arg);
}
/*----------------------------------------------------------------------------------*/
void GtpuEncap::ProcessBatch(Context *ctx, bess::PacketBatch *batch) {
int cnt = batch->cnt();
int hits = 0;
Expand Down Expand Up @@ -342,4 +355,8 @@ CommandResponse GtpuEncap::Init(const bess::pb::GtpuEncapArg &arg) {
return CommandSuccess();
}
/*----------------------------------------------------------------------------------*/
std::string GtpuEncap::GetDesc() const {
return bess::utils::Format("%zu sessions", (size_t)rte_hash_count(session_map));
}
/*----------------------------------------------------------------------------------*/
ADD_MODULE(GtpuEncap, "gtpu_encap", "first version of gtpu encap module")
3 changes: 3 additions & 0 deletions core/modules/gtpu_encap.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,10 @@ class GtpuEncap final : public Module {
CommandResponse RemoveSessionRecord(
const bess::pb::GtpuEncapRemoveSessionRecordArg &arg);
CommandResponse ShowRecords(const bess::pb::EmptyArg &);
CommandResponse ShowCount(const bess::pb::EmptyArg &);
void ProcessBatch(Context *ctx, bess::PacketBatch *batch) override;
// returns the number of active UE sessions
std::string GetDesc() const override;

private:
int dp_session_create(struct session_info *entry);
Expand Down