Skip to content

Commit 2b6f329

Browse files
added example parameters + proper readme + minor adjustments
1 parent e8585c2 commit 2b6f329

20 files changed

+224
-8
lines changed

README.md

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,49 @@
1-
Requries Python 3.5 and Gurobi 7.0.
1+
# B-JointSP
2+
3+
B-JointSP is an optimization problem focusing on the joint scaling and placement (called embedding) of NFV network services, consisting of interconnected virtual network functions (VNFs). The exceptional about B-JointSP is its consideration of realistic, bidirectional network services, in which flows return to their sources. It even supports stateful VNFs, that need to be traversed by the same flows in both upstream and downstream direction. Furthermore, B-JointSP allows the reuse of VNFs across different network services and supports physical network functions.
4+
5+
This repository provides the source code for an optimization approach formulated as MIP that can be linearized as MILP and solved with Gurobi. We also provide a fast heuristic algorithm.
6+
7+
## Installation requirements
8+
9+
* [Python 3.5](https://www.python.org/)
10+
* [Gurobi 7.0](http://www.gurobi.com/) and [gurobipy](http://www.gurobi.com/documentation/6.5/quickstart_mac/the_gurobi_python_interfac.html) for the optimization approach
11+
12+
## Usage/Execution
13+
14+
### Parameters
15+
16+
To describe an embedding scenario, the following parameters are required:
17+
18+
* A substrate network, with node and link capacities as well as link delays
19+
* At least one network service (template), specifying the different kinds of VNFs in the service and their interconnection
20+
* Sources corresponding to the source components of the specified services and located at certain network nodes. Each source specifies at least one outgoing flow (and its flow strength).
21+
22+
Optional parameters:
23+
24+
* Fixed locations of physical network functions
25+
* A previously existing embedding to be optimized
26+
27+
Each of these parameters is described by a separate csv file. A scenario description (also csv) references these individual parameters. See the `parameters` folder for examples.
28+
29+
When running the MIP or the heuristic, the detailed embedding results are stored in `parameters/results` and logs (for debugging or checking the progress) are in `parameters/logs`.
30+
31+
### MIP
32+
33+
To run the MIP and obtain optimal results (with Gurobi), use the following command: `python main.py mip <scenario> (<repetition>)`, where `<scenario>` is the path to a scenario file and `(<repetition>)` is an optional repetition number just for distinguishing different runs with the same parameters.
34+
35+
For example, `python main.py mip parameters/scenarios/simple.csv` solves a simple embedding example, where a bidirectional network service with a firewall and a vCDN is embedded into a four-node network.
36+
37+
### Heuristic
38+
39+
To run the heuristic algorithm, use the command `python main.py heuristic <scenario> (<seed>)`. Again, `<seed>` specifies the scenario file and `(<seed>)` is an optional seed for randomization.
40+
41+
The same example embedding can also be performed with the heuristic: `python main.py heuristic parameters/scenarios/simple.csv`.
42+
43+
## Contact
44+
45+
This source code belongs to the paper "**Scaling and Placing Bidirectional Services with Stateful Virtual and Physical Network Functions**" submitted to IEEE NetSoft 2018 by Sevil Dräxler, Stefan Schneider, and Holger Karl.
46+
47+
Lead developer: Stefan Schneider
48+
49+
For questions or support, please use GitHub's issue system.

main.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@
1717

1818
# read scenario input
1919
if len(sys.argv) < 3:
20-
print("MIP usage: python3 main.py mip <scenario> (<repetition>)")
21-
print("Heuristic usage: python3 main.py heuristic <scenario> (<seed>)")
22-
print("Pareto usage: python3 main.py pareto <scenario> <objective> <bound1> <bound2> <bound3>")
20+
print("MIP usage: python main.py mip <scenario> (<repetition>)")
21+
print("Heuristic usage: python main.py heuristic <scenario> (<seed>)")
22+
print("Pareto usage: python main.py pareto <scenario> <objective> <bound1> <bound2> <bound3>")
2323
# print("Pareto usage: python3 main.py pareto <scenario> <objective> <bound1> <bound2>")
2424
exit(1)
2525
method = sys.argv[1]
@@ -68,8 +68,8 @@
6868
# set up logging into file Data/logs/heuristic/scenario_timestamp_seed.log
6969
# logging.disable(logging.CRITICAL) # disable logging
7070
timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
71-
os.makedirs("Data/logs/heuristic/obj{}".format(obj), exist_ok=True)
72-
logging.basicConfig(filename="Data/logs/heuristic/obj{}/{}_{}_{}.log".format(obj, os.path.basename(scenario)[:-4], timestamp, seed),
71+
os.makedirs("parameters/logs/heuristic/obj{}".format(obj), exist_ok=True)
72+
logging.basicConfig(filename="parameters/logs/heuristic/obj{}/{}_{}_{}.log".format(obj, os.path.basename(scenario)[:-4], timestamp, seed),
7373
level=logging.DEBUG, format="%(asctime)s(%(levelname)s):\t%(message)s", datefmt="%H:%M:%S")
7474

7575
logging.info("Starting initial embedding at {}".format(timestamp))
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# substrate network: square of four nodes
2+
# only use spaces as delimiter (no tabs)
3+
# Nodes: id cpu mem
4+
0 5 5
5+
1 5 5
6+
2 5 5
7+
3 5 5
8+
9+
# DIRECTED Links: src_id sink_id cap delay
10+
0 1 10 1
11+
1 0 10 1
12+
1 2 10 1
13+
2 1 10 1
14+
2 3 10 1
15+
3 2 10 1
16+
3 0 10 1
17+
0 3 10 1

parameters/optional/events.csv

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# sequence of new scenario inputs to model events
2+
# allows arbitrary changes (even multiple at once), e.g., adjusted/new/deleted templates, sources, fixed instances, but not changing the substrate network
3+
# need to add corresponding templates before adding new sources such that the source components can be recognized
4+
5+
# syntax:
6+
# templates: file_paths (separated by white spaces)
7+
# sources: file_path
8+
# fixed: file_path
9+
10+
sources: ../sources/sources2.csv
11+
sources: ../sources/sources3.csv

parameters/optional/fixed.csv

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# fixed instances (e.g., legacy NFs): node_id component
2+
1 CDN1
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# previous embedding (only instance locations): node component
2+
0 S1
3+
1 FW
4+
1 CDN1
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# previous embedding (only instance locations): node component
2+
0 S1
3+
0 S2
4+
1 FW
5+
1 CDN1
6+
2 vCDN2
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# scenario: collection of all inputs to the optimization problem (relative file path)
2+
# order and identifiers (e.g., "network:") are fixed and must not be changed; additional whitespaces (eg., in names or at the end of a line) or inline comments are not allowed
3+
4+
# substrate network, 1+ templates (separated by whitespace), previous embedding, data sources, fixed instances
5+
# the heuristic ignores prev_embedding and the mip ignores events
6+
network: ../networks/square_network.csv
7+
templates: ../templates/cdn1.csv ../templates/cdn2.csv
8+
sources: ../sources/sources1.csv
9+
fixed: ../optional/fixed.csv
10+
events: ../optional/events.csv
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# scenario: collection of all inputs to the optimization problem (relative file path)
2+
# order and identifiers (e.g., "network:") are fixed and must not be changed; additional whitespaces (eg., in names or at the end of a line) or inline comments are not allowed
3+
4+
# substrate network, 1+ templates (separated by whitespace), previous embedding, data sources, fixed instances
5+
network: ../networks/square_network.csv
6+
templates: ../templates/cdn1.csv ../templates/cdn2.csv
7+
sources: ../sources/sources1.csv
8+
fixed: ../optional/fixed.csv
9+
prev_embedding:
10+
events:
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# scenario: collection of all inputs to the optimization problem (relative file path)
2+
# order and identifiers (e.g., "network:") are fixed and must not be changed; additional whitespaces (eg., in names or at the end of a line) or inline comments are not allowed
3+
4+
# substrate network, 1+ templates (separated by whitespace), previous embedding, data sources, fixed instances
5+
network: ../networks/square_network.csv
6+
templates: ../templates/cdn1.csv ../templates/cdn2.csv
7+
sources: ../sources/sources2.csv
8+
fixed: ../optional/fixed.csv
9+
prev_embedding: ../optional/prev_embedding1.csv
10+
events:
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# scenario: collection of all inputs to the optimization problem (relative file path)
2+
# order and identifiers (e.g., "network:") are fixed and must not be changed; additional whitespaces (eg., in names or at the end of a line) or inline comments are not allowed
3+
4+
# substrate network, 1+ templates (separated by whitespace), previous embedding, data sources, fixed instances
5+
network: ../networks/square_network.csv
6+
templates: ../templates/cdn1.csv ../templates/cdn2.csv
7+
sources: ../sources/sources3.csv
8+
fixed: ../optional/fixed.csv
9+
prev_embedding: ../optional/prev_embedding2.csv
10+
events:

parameters/scenarios/simple.csv

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# scenario: collection of all inputs to the optimization problem (relative file path)
2+
# order and identifiers (e.g., "network:") are fixed and must not be changed; additional whitespaces (eg., in names or at the end of a line) or inline comments are not allowed
3+
4+
# substrate network, 1+ templates (separated by whitespace), previous embedding, data sources, fixed instances
5+
network: ../networks/square_network.csv
6+
templates: ../templates/cdn1.csv
7+
sources: ../sources/sources1.csv
8+
fixed:
9+
prev_embedding:
10+
events:

parameters/sources/sources1.csv

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# data sources: node_id source_component data_rate
2+
# flows: (flow_id data_rate)+
3+
0 S1 1 1

parameters/sources/sources2.csv

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# data sources: node_id source_component data_rate
2+
# flows: (flow_id data_rate)+
3+
0 S1 1 1
4+
0 S2 2 1

parameters/sources/sources3.csv

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# data sources: node_id source_component data_rate
2+
# flows: (flow_id data_rate)+
3+
0 S1 1 1
4+
0 S2 2 1
5+
3 S2 3 1

parameters/templates/cdn1.csv

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# template: S1<->FW<->CDN1
2+
# name
3+
cdn1
4+
5+
# Components: name type stateful inputs in_back outputs out_back [cpu_coeff] [mem_coeff] [[outgoing_coeff]] [[outgoing_back]]
6+
# type={source, normal, end}; values separated by tabs; coeff separated by comma - first fw_in, then bw_in, then +constant; outgoing for diff outputs separated by ;
7+
S1 source True 0 1 1 0 [0,0] [0,0] [] []
8+
FW normal True 1 1 1 1 [1,1,0] [1,1,0] [[1,0]] [[1,0]]
9+
CDN1 end False 1 0 0 1 [1,0] [1,0] [] [[1,0]]
10+
11+
# Arcs: direction src_name src_output dest_name dest_input max_delay
12+
forward S1 0 FW 0 20
13+
forward FW 0 CDN1 0 20
14+
backward CDN1 0 FW 0 20
15+
backward FW 0 S1 0 20

parameters/templates/cdn2.csv

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# template: S2<->FW<->vCDN2
2+
# name
3+
cdn2
4+
5+
# Components: name type stateful inputs in_back outputs out_back [cpu_coeff] [mem_coeff] [[outgoing_coeff]] [[outgoing_back]]
6+
# type={source, normal, end}; values separated by tabs; coeff separated by comma - first fw_in, then bw_in, then +constant; outgoing for diff outputs separated by ;
7+
S2 source True 0 1 1 0 [0,0] [0,0] [] []
8+
FW normal True 1 1 1 1 [1,1,0] [1,1,0] [[1,0]] [[1,0]]
9+
vCDN2 end False 1 0 0 1 [1,0] [1,0] [] [[1,0]]
10+
11+
# Arcs: direction src_name src_output dest_name dest_input max_delay
12+
forward S2 0 FW 0 20
13+
forward FW 0 vCDN2 0 20
14+
backward vCDN2 0 FW 0 20
15+
backward FW 0 S2 0 20

parameters/templates/unidir_chain.csv

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# simple chain template: S1->A->B
2+
# name
3+
chain
4+
5+
# Components: name type stateful inputs in_back outputs out_back [cpu_coeff] [mem_coeff] [[outgoing_coeff]] [[outgoing_back]]
6+
# type={source, normal, end}; values separated by tabs; coeff separated by comma - first fw_in, then bw_in, then +constant; outgoing for diff outputs separated by ;
7+
S1 source True 0 0 1 0 [0] [0] [] []
8+
A normal False 1 0 1 0 [1,0] [1,0] [[1,0]] []
9+
B normal False 1 0 0 0 [1,0] [1,0] [] []
10+
11+
# Arcs: direction src_name src_output dest_name dest_input max_delay
12+
forward S1 0 A 0 20
13+
forward A 0 B 0 20

parameters/templates/video.csv

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# video streaming template with memory idle consumption (cache and server)
2+
# forward: streaming requests with low dr to cache and server
3+
# backward: high dr video stream via the cache that is possibly optimized for mobile devices when loaded from the server (distinguished with DPI)
4+
5+
# name
6+
video
7+
8+
# Components: name type stateful inputs in_back outputs out_back [cpu_coeff] [mem_coeff] [[outgoing_coeff]] [[outgoing_back]]
9+
# type={source, normal, end}; values separated by tabs; coeff separated by comma - first fw_in, then bw_in, then +constant; outgoing for diff outputs separated by ;
10+
S2 source True 0 1 1 0 [0,0] [0,0] [] []
11+
Cache2 normal False 1 2 1 1 [1,1,1,0] [2,2,2,0.5] [[1,0]] [[2,2,0]]
12+
Server2 end False 1 0 0 1 [1,0] [2,0.5] [] [[1.5,0]]
13+
DPI normal False 0 1 0 2 [1,0] [1,0] [] [[0.9,0];[0.1,0]]
14+
VidOpt normal False 0 1 0 1 [2,0] [1,0] [] [[0.5,0]]
15+
16+
# Arcs: direction src_name src_output dest_name dest_input max_delay
17+
forward S2 0 Cache2 0 50
18+
forward Cache2 0 Server2 0 50
19+
backward Server2 0 DPI 0 50
20+
backward DPI 0 Cache2 0 50
21+
backward DPI 1 VidOpt 0 50
22+
backward VidOpt 0 Cache2 1 50
23+
backward Cache2 0 S2 0 50

read_write/reader.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,11 +191,11 @@ def read_prev_embedding(file, components):
191191
if len(row) == 2:
192192
try:
193193
# get the component with the specified name: first (and only) element with component name
194-
component = list(filter(lambda x: x.name == row[0], components))[0]
194+
component = list(filter(lambda x: x.name == row[1], components))[0]
195195
except IndexError:
196196
raise ValueError("Component {} of prev overlay unknown (not used in any template).".format(row[1]))
197197

198-
prev_embedding[component].append(row[1])
198+
prev_embedding[component].append(row[0])
199199
return prev_embedding
200200

201201

0 commit comments

Comments
 (0)