First commit

This commit is contained in:
Gaetan Longree 2018-05-11 15:51:48 +02:00
commit 4411d5800e
87 changed files with 6573 additions and 0 deletions

62
BENCHMARKING/README.md Normal file
View File

@ -0,0 +1,62 @@
# Benchmarking
This section provides the script to launch and reproduce the benchmarks perfromed for this project (and whoses results are posted on the root README file).
## Preparing the environment
Prior to launching the benchmarks, you must launch the [pre deployment script](https://git.cetic.be/stages/unikernels/blob/feature/stagelongree2018/DEPLOYMENT/pre_deployment_installation.sh) provided in the DEPLOYMENT folder.
Then you must install the benchmarking tools using the [install\_bench\_tools.sh](https://git.cetic.be/stages/unikernels/blob/feature/stagelongree2018/BENCHMARKING/install_bench_tools.sh) script.
This script will install the following tools:
* dnsperf and its dependencies for the DNS benchmark (by Nominum)
* wrk2 for the web server benchmark (by Gil Tene, based on original wrk by Will Glozer)
## Launching the target instance
To launch an instance to benchmark, launch the **bench_*.sh** scripts:
* bench\_container\_dns.sh
* bench\_container\_web.sh
* bench\_unikernel\_dns.sh
* bench\_unikernel\_web.sh
The scripts will:
* build the unikernel/container
* stop all running VMs and containers
* launch the unikernel/container, attaching it to the default network
If you're launching a container, the ports will be mapped on launch.
If you're launching a unikernel, two rules will be inserted in iptables to allow port forwarding to the internal network.
## Launching the benchmark
The benchmark scripts are written in python and make use of the tools installed with the install\_bench\_tools.sh script.
The web and DNS server benchmarking scripts are written to use 4 threads and simulate 100 virtual connections to the target server.
### Web server benchmark
To launch the web server, user `python3 web_unik_benchmark.py [server_ip_address]`.
The benchmark will send HTTP requests to the server for 5 minutes, starting at a pace of 100 queries per second. After 5 minutes it will save the data in a .csv file and then will relaunch the process incrementing by another 100 queries per second.
### DNS server benchmark
To launch the web server, user `python3 web_<type>_benchmark.py [server_ip_address]`.
The benchmark will send DNS requests to the server for 5 minutes, starting at a pace of 100 queries per second. After 5 minutes it will save the data in a .csv file and then will relaunch the process incrementing by another 100 queries per second.
### Boot time benchmark
To launch the web server, user `python3 startup_<type>_benchmark.py [starting number of instances]`.
The benchmark will start by building and launching the given number of VM or container instances. Then, for 20 minutes, it will send the stop a random instance, send the start command and calculate the time between the start command being sent, and when the target instance responds to a single ping. For each stop/start process, the recorded time is then inserted into a csv file. After 20 minutes, the number of instances is incremented by 10 and the process is repeated. This process repeats itself until 140 instances are launched.
## Cleaning up the environment
The individual instance scripts do not stop the instances launched, this needs to be done manually.
However, each instance start script will stop the currently running containers and virtual machines, as will the boot time benchmark scripts.
To clean up the iptable rules created for the unikernels use the `./bench_unikernel_cleanup.sh` script.
To clean up all the instances and iptable rule use the `./cleanup_all.sh` script.

Binary file not shown.

View File

@ -0,0 +1,28 @@
TEST_RUN,QUERIES_SENT,QUERIES_COMPLETED,QUERIES_LOST,QUERIES_PER_SECOND,AVG_LATENCY_SECONDS,MIN,MAX,LATENCY_STD_DEV_SECONDS
1,30300,30300,0,100.999942,0.000435,0.000677,0.038042,0.000463
2,60600,60600,0,201.999868,0.000413,0.000548,0.045776,0.000575
3,90900,90900,0,302.999799,0.000410,0.000522,0.045355,0.000601
4,120000,120000,0,399.999763,0.000469,0.000531,0.047507,0.000620
5,150300,150300,0,500.999641,0.000401,0.000499,0.050776,0.000639
6,180600,180600,0,601.999573,0.000399,0.000448,0.048009,0.000649
7,210900,210900,0,702.999531,0.000397,0.000436,0.048220,0.000649
8,240000,240000,0,799.999397,0.000457,0.000530,0.050598,0.000664
9,270300,270300,0,900.999381,0.000405,0.000447,0.049469,0.000682
10,300600,300600,0,1001.999476,0.000387,0.000452,0.048770,0.000673
11,330900,330900,0,1102.999158,0.000385,0.000463,0.051058,0.000625
12,360000,360000,0,1199.999244,0.000468,0.000455,0.064912,0.000742
13,390300,390300,0,1300.999553,0.000407,0.000430,0.053302,0.000715
14,420600,420600,0,1401.999248,0.000368,0.000443,0.050178,0.000646
15,450900,450900,0,1502.999083,0.000398,0.000420,0.049944,0.000696
16,480000,480000,0,1599.998837,0.000477,0.000455,0.062380,0.000803
17,510300,510300,0,1700.998883,0.000386,0.000421,0.051476,0.000672
18,540600,540600,0,1801.998793,0.000376,0.000405,0.061594,0.000691
19,570900,570900,0,1902.998744,0.000401,0.000392,0.074226,0.000725
20,600000,600000,0,1999.999260,0.000446,0.000447,0.060142,0.000730
21,630300,630300,0,2100.998823,0.000386,0.000388,0.055958,0.000697
22,660600,660600,0,2201.998349,0.000384,0.000394,0.063996,0.000722
23,690900,690900,0,2302.998572,0.000389,0.000395,0.052586,0.000711
24,720000,720000,0,2399.998472,0.000435,0.000440,0.057137,0.000699
25,750300,750300,0,2500.998533,0.000402,0.000391,0.072312,0.000743
26,780600,780600,0,2601.998439,0.000385,0.000389,0.064135,0.000734
27,810900,810900,0,2702.998423,0.000386,0.000393,0.073673,0.000745
1 TEST_RUN QUERIES_SENT QUERIES_COMPLETED QUERIES_LOST QUERIES_PER_SECOND AVG_LATENCY_SECONDS MIN MAX LATENCY_STD_DEV_SECONDS
2 1 30300 30300 0 100.999942 0.000435 0.000677 0.038042 0.000463
3 2 60600 60600 0 201.999868 0.000413 0.000548 0.045776 0.000575
4 3 90900 90900 0 302.999799 0.000410 0.000522 0.045355 0.000601
5 4 120000 120000 0 399.999763 0.000469 0.000531 0.047507 0.000620
6 5 150300 150300 0 500.999641 0.000401 0.000499 0.050776 0.000639
7 6 180600 180600 0 601.999573 0.000399 0.000448 0.048009 0.000649
8 7 210900 210900 0 702.999531 0.000397 0.000436 0.048220 0.000649
9 8 240000 240000 0 799.999397 0.000457 0.000530 0.050598 0.000664
10 9 270300 270300 0 900.999381 0.000405 0.000447 0.049469 0.000682
11 10 300600 300600 0 1001.999476 0.000387 0.000452 0.048770 0.000673
12 11 330900 330900 0 1102.999158 0.000385 0.000463 0.051058 0.000625
13 12 360000 360000 0 1199.999244 0.000468 0.000455 0.064912 0.000742
14 13 390300 390300 0 1300.999553 0.000407 0.000430 0.053302 0.000715
15 14 420600 420600 0 1401.999248 0.000368 0.000443 0.050178 0.000646
16 15 450900 450900 0 1502.999083 0.000398 0.000420 0.049944 0.000696
17 16 480000 480000 0 1599.998837 0.000477 0.000455 0.062380 0.000803
18 17 510300 510300 0 1700.998883 0.000386 0.000421 0.051476 0.000672
19 18 540600 540600 0 1801.998793 0.000376 0.000405 0.061594 0.000691
20 19 570900 570900 0 1902.998744 0.000401 0.000392 0.074226 0.000725
21 20 600000 600000 0 1999.999260 0.000446 0.000447 0.060142 0.000730
22 21 630300 630300 0 2100.998823 0.000386 0.000388 0.055958 0.000697
23 22 660600 660600 0 2201.998349 0.000384 0.000394 0.063996 0.000722
24 23 690900 690900 0 2302.998572 0.000389 0.000395 0.052586 0.000711
25 24 720000 720000 0 2399.998472 0.000435 0.000440 0.057137 0.000699
26 25 750300 750300 0 2500.998533 0.000402 0.000391 0.072312 0.000743
27 26 780600 780600 0 2601.998439 0.000385 0.000389 0.064135 0.000734
28 27 810900 810900 0 2702.998423 0.000386 0.000393 0.073673 0.000745

View File

@ -0,0 +1,28 @@
TEST_RUN,QUERIES_SENT,QUERIES_COMPLETED,QUERIES_LOST,QUERIES_PER_SECOND,AVG_LATENCY_SECONDS,MIN,MAX,LATENCY_STD_DEV_SECONDS
1,30300,30300,0,100.999941,0.006355,0.005415,0.098812,0.002519
2,60600,60600,0,201.999860,0.005617,0.005722,0.080283,0.002087
3,90900,90900,0,302.999889,0.005715,0.005411,0.101761,0.002100
4,120000,120000,0,399.999672,0.006401,0.005320,0.158964,0.001903
5,150300,150300,0,500.999711,0.005402,0.004774,0.271349,0.003626
6,180600,180600,0,601.999603,0.006268,0.004755,0.725090,0.007226
7,210900,210900,0,702.999536,0.011069,0.004425,0.618359,0.015394
8,240000,240000,0,799.937413,0.037150,0.004729,0.615609,0.036375
9,253892,253892,0,846.044238,0.118990,0.041761,8.319091,0.055582
10,255867,255867,0,852.822877,0.118098,0.046127,5.168513,0.024260
11,255428,255428,0,851.255666,0.118290,0.046994,4.080020,0.019123
12,253791,253791,0,845.691776,0.119118,0.046585,7.608933,0.036147
13,254861,254861,0,849.297151,0.118604,0.042165,4.014139,0.018720
14,254055,254055,0,846.612175,0.118889,0.037720,7.076644,0.033647
15,255951,255951,0,852.928016,0.118049,0.035549,0.581656,0.006604
16,254741,254741,0,849.026353,0.118526,0.044648,2.758404,0.013401
17,255579,255579,0,851.654708,0.118254,0.037696,0.587303,0.006576
18,250233,250233,0,834.063092,0.120648,0.050919,6.691459,0.042768
19,253722,253722,0,845.695581,0.119023,0.051268,0.693072,0.007301
20,252384,252384,0,841.134621,0.119705,0.042426,7.830838,0.039162
21,255698,255698,0,852.217853,0.118158,0.043026,0.596498,0.006608
22,251706,251706,0,838.762075,0.120080,0.042971,7.658614,0.042178
23,254452,254452,0,848.033594,0.118793,0.047975,0.570417,0.006341
24,252446,252446,0,841.183336,0.119791,0.046854,7.977354,0.037990
25,253242,253242,0,843.946885,0.119344,0.046943,0.708790,0.006546
26,252173,252173,0,840.376755,0.119819,0.049304,6.509316,0.030894
27,250928,250928,0,836.353101,0.120345,0.042280,6.734916,0.037482
1 TEST_RUN QUERIES_SENT QUERIES_COMPLETED QUERIES_LOST QUERIES_PER_SECOND AVG_LATENCY_SECONDS MIN MAX LATENCY_STD_DEV_SECONDS
2 1 30300 30300 0 100.999941 0.006355 0.005415 0.098812 0.002519
3 2 60600 60600 0 201.999860 0.005617 0.005722 0.080283 0.002087
4 3 90900 90900 0 302.999889 0.005715 0.005411 0.101761 0.002100
5 4 120000 120000 0 399.999672 0.006401 0.005320 0.158964 0.001903
6 5 150300 150300 0 500.999711 0.005402 0.004774 0.271349 0.003626
7 6 180600 180600 0 601.999603 0.006268 0.004755 0.725090 0.007226
8 7 210900 210900 0 702.999536 0.011069 0.004425 0.618359 0.015394
9 8 240000 240000 0 799.937413 0.037150 0.004729 0.615609 0.036375
10 9 253892 253892 0 846.044238 0.118990 0.041761 8.319091 0.055582
11 10 255867 255867 0 852.822877 0.118098 0.046127 5.168513 0.024260
12 11 255428 255428 0 851.255666 0.118290 0.046994 4.080020 0.019123
13 12 253791 253791 0 845.691776 0.119118 0.046585 7.608933 0.036147
14 13 254861 254861 0 849.297151 0.118604 0.042165 4.014139 0.018720
15 14 254055 254055 0 846.612175 0.118889 0.037720 7.076644 0.033647
16 15 255951 255951 0 852.928016 0.118049 0.035549 0.581656 0.006604
17 16 254741 254741 0 849.026353 0.118526 0.044648 2.758404 0.013401
18 17 255579 255579 0 851.654708 0.118254 0.037696 0.587303 0.006576
19 18 250233 250233 0 834.063092 0.120648 0.050919 6.691459 0.042768
20 19 253722 253722 0 845.695581 0.119023 0.051268 0.693072 0.007301
21 20 252384 252384 0 841.134621 0.119705 0.042426 7.830838 0.039162
22 21 255698 255698 0 852.217853 0.118158 0.043026 0.596498 0.006608
23 22 251706 251706 0 838.762075 0.120080 0.042971 7.658614 0.042178
24 23 254452 254452 0 848.033594 0.118793 0.047975 0.570417 0.006341
25 24 252446 252446 0 841.183336 0.119791 0.046854 7.977354 0.037990
26 25 253242 253242 0 843.946885 0.119344 0.046943 0.708790 0.006546
27 26 252173 252173 0 840.376755 0.119819 0.049304 6.509316 0.030894
28 27 250928 250928 0 836.353101 0.120345 0.042280 6.734916 0.037482

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,53 @@
TEST_RUN,QUERIES_SENT,QUERIES_PER_SECOND,AVG_LATENCY_MILLISECONDS,MAX_LATENCY_MILLISECONDS,LATENCY_STD_DEV_PERCENT
1,30004,100.01,1.52,15.04,1.22
2,60004,200.01,5.53,98.24,15.26
3,86523,errors:,10.34,86.59,17.49
4,97188,errors:,14.77,100.48,21.82
5,150004,500.01,1.35,15.90,0.85
6,180004,600.01,1.29,11.84,772.32
7,210004,700.01,1.33,12.25,814.78
8,240004,800.01,1.32,16.99,835.06
9,269992,899.97,1.41,15.10,0.89
10,299965,999.88,1.61,43.87,1.16
11,329977,1099.92,1.31,19.14,0.86
12,359967,1199.89,1.30,16.26,0.86
13,308094,errors:,1.72,51.23,2.43
14,419961,1399.86,1.28,16.22,0.85
15,449957,1499.86,1.30,16.86,0.91
16,479956,1599.84,1.27,18.67,0.90
17,509947,1699.82,1.47,18.24,1.02
18,539937,1799.79,1.35,20.96,0.95
19,518643,errors:,1.53,48.03,2.09
20,599924,1999.74,1.48,15.46,1.04
21,456201,errors:,2.73,55.87,3.63
22,659914,2199.70,1.36,20.53,1.02
23,689901,2299.67,1.31,18.86,0.97
24,463255,errors:,2.63,64.32,3.49
25,749893,2499.64,1.44,18.54,1.06
26,779887,2599.62,1.32,18.93,0.98
27,710465,errors:,2.13,64.99,3.10
28,839872,2799.58,1.46,24.35,1.09
29,869872,2899.56,2.28,1.00,23.82
30,753759,errors:,1.85,57.95,2.51
31,929856,3099.52,1.35,22.18,1.08
32,959839,3199.46,1.49,23.01,1.16
33,940349,errors:,2.46,73.92,3.68
34,887274,errors:,2.38,63.30,3.64
35,1018333,errors:,1.45,38.02,1.29
36,809203,errors:,2.66,229.25,3.51
37,1109817,3699.39,1.48,25.94,1.17
38,1128419,errors:,1.27,24.27,1.09
39,1169809,3899.36,1.44,23.55,1.15
40,758943,errors:,3.08,55.78,3.64
41,971669,errors:,2.02,63.10,3.14
42,1120557,errors:,1.99,59.04,3.20
43,1073221,errors:,2.55,68.48,3.99
44,1108674,errors:,2.19,59.17,3.47
45,1107577,errors:,1.92,75.39,2.92
46,1020400,errors:,2.76,74.82,4.07
47,1205310,errors:,2.44,76.22,3.77
48,1097203,errors:,1.71,63.36,2.49
49,1190790,errors:,2.54,68.93,3.95
50,1154937,errors:,2.71,73.34,3.99
51,1152226,errors:,1.86,68.10,2.71
52,1139356,errors:,2.49,64.61,3.77
1 TEST_RUN QUERIES_SENT QUERIES_PER_SECOND AVG_LATENCY_MILLISECONDS MAX_LATENCY_MILLISECONDS LATENCY_STD_DEV_PERCENT
2 1 30004 100.01 1.52 15.04 1.22
3 2 60004 200.01 5.53 98.24 15.26
4 3 86523 errors: 10.34 86.59 17.49
5 4 97188 errors: 14.77 100.48 21.82
6 5 150004 500.01 1.35 15.90 0.85
7 6 180004 600.01 1.29 11.84 772.32
8 7 210004 700.01 1.33 12.25 814.78
9 8 240004 800.01 1.32 16.99 835.06
10 9 269992 899.97 1.41 15.10 0.89
11 10 299965 999.88 1.61 43.87 1.16
12 11 329977 1099.92 1.31 19.14 0.86
13 12 359967 1199.89 1.30 16.26 0.86
14 13 308094 errors: 1.72 51.23 2.43
15 14 419961 1399.86 1.28 16.22 0.85
16 15 449957 1499.86 1.30 16.86 0.91
17 16 479956 1599.84 1.27 18.67 0.90
18 17 509947 1699.82 1.47 18.24 1.02
19 18 539937 1799.79 1.35 20.96 0.95
20 19 518643 errors: 1.53 48.03 2.09
21 20 599924 1999.74 1.48 15.46 1.04
22 21 456201 errors: 2.73 55.87 3.63
23 22 659914 2199.70 1.36 20.53 1.02
24 23 689901 2299.67 1.31 18.86 0.97
25 24 463255 errors: 2.63 64.32 3.49
26 25 749893 2499.64 1.44 18.54 1.06
27 26 779887 2599.62 1.32 18.93 0.98
28 27 710465 errors: 2.13 64.99 3.10
29 28 839872 2799.58 1.46 24.35 1.09
30 29 869872 2899.56 2.28 1.00 23.82
31 30 753759 errors: 1.85 57.95 2.51
32 31 929856 3099.52 1.35 22.18 1.08
33 32 959839 3199.46 1.49 23.01 1.16
34 33 940349 errors: 2.46 73.92 3.68
35 34 887274 errors: 2.38 63.30 3.64
36 35 1018333 errors: 1.45 38.02 1.29
37 36 809203 errors: 2.66 229.25 3.51
38 37 1109817 3699.39 1.48 25.94 1.17
39 38 1128419 errors: 1.27 24.27 1.09
40 39 1169809 3899.36 1.44 23.55 1.15
41 40 758943 errors: 3.08 55.78 3.64
42 41 971669 errors: 2.02 63.10 3.14
43 42 1120557 errors: 1.99 59.04 3.20
44 43 1073221 errors: 2.55 68.48 3.99
45 44 1108674 errors: 2.19 59.17 3.47
46 45 1107577 errors: 1.92 75.39 2.92
47 46 1020400 errors: 2.76 74.82 4.07
48 47 1205310 errors: 2.44 76.22 3.77
49 48 1097203 errors: 1.71 63.36 2.49
50 49 1190790 errors: 2.54 68.93 3.95
51 50 1154937 errors: 2.71 73.34 3.99
52 51 1152226 errors: 1.86 68.10 2.71
53 52 1139356 errors: 2.49 64.61 3.77

View File

@ -0,0 +1,2 @@
TEST_RUN,QUERIES_SENT,QUERIES_PER_SECOND,AVG_LATENCY_MILLISECONDS,MAX_LATENCY_MILLISECONDS,LATENCY_STD_DEV_PERCENT
1,0,errors:,-,0.00,-
1 TEST_RUN QUERIES_SENT QUERIES_PER_SECOND AVG_LATENCY_MILLISECONDS MAX_LATENCY_MILLISECONDS LATENCY_STD_DEV_PERCENT
2 1 0 errors: - 0.00 -

View File

@ -0,0 +1,37 @@
TEST_RUN,QUERIES_SENT,QUERIES_PER_SECOND,AVG_LATENCY_MILLISECONDS,MAX_LATENCY_MILLISECONDS,LATENCY_STD_DEV_PERCENT
1,30004,100.01,3.65,18.64,2.13
2,60004,200.01,4.56,22.26,3.23
3,90004,300.01,3.08,217.60,3.28
4,120004,400.01,4.33,136.96,4.11
5,150004,500.01,4.30,95.36,3.54
6,180004,600.01,3.24,50.69,2.03
7,210004,700.01,2.92,26.43,1.83
8,240004,800.01,5.75,40.54,5.37
9,269992,899.97,4.49,29.44,3.88
10,299986,999.94,3.25,39.71,2.00
11,329965,1099.86,7.52,37.73,6.28
12,359965,1199.87,10.04,41.28,7.78
13,389961,1299.87,5.04,38.02,4.26
14,419961,1399.87,3.78,37.63,2.89
15,449956,1499.84,5.93,36.70,5.12
16,479952,1599.84,4.51,1.02,24.24
17,509941,1699.80,3.96,37.34,3.19
18,539931,1799.77,8.07,40.10,6.09
19,569930,1899.75,4.51,51.68,4.00
20,599905,1999.61,10.44,43.14,7.12
21,629914,2099.71,5.53,43.97,4.45
22,659898,2199.67,5.74,44.67,4.24
23,689899,2299.66,6.34,49.92,5.65
24,719899,2399.65,11.37,54.05,8.06
25,749895,2499.63,8.07,54.66,5.78
26,779884,2599.59,8.45,50.14,7.29
27,809827,2699.31,15.97,59.55,8.63
28,734062,2446.83,5.45,37.98,10.68
29,869861,2899.54,12.20,58.46,8.84
30,784697,2615.19,6.37,38.34,11.19
31,818727,2728.72,3.71,35.82,8.43
32,632347,2106.63,41.77,1.71,33.16
33,674216,2246.32,47.19,1.60,28.58
34,606538,2021.69,1.06,2.03,35.14
35,719335,2396.51,47.68,1.58,26.97
36,590733,1969.06,1.13,2.27,39.42
1 TEST_RUN QUERIES_SENT QUERIES_PER_SECOND AVG_LATENCY_MILLISECONDS MAX_LATENCY_MILLISECONDS LATENCY_STD_DEV_PERCENT
2 1 30004 100.01 3.65 18.64 2.13
3 2 60004 200.01 4.56 22.26 3.23
4 3 90004 300.01 3.08 217.60 3.28
5 4 120004 400.01 4.33 136.96 4.11
6 5 150004 500.01 4.30 95.36 3.54
7 6 180004 600.01 3.24 50.69 2.03
8 7 210004 700.01 2.92 26.43 1.83
9 8 240004 800.01 5.75 40.54 5.37
10 9 269992 899.97 4.49 29.44 3.88
11 10 299986 999.94 3.25 39.71 2.00
12 11 329965 1099.86 7.52 37.73 6.28
13 12 359965 1199.87 10.04 41.28 7.78
14 13 389961 1299.87 5.04 38.02 4.26
15 14 419961 1399.87 3.78 37.63 2.89
16 15 449956 1499.84 5.93 36.70 5.12
17 16 479952 1599.84 4.51 1.02 24.24
18 17 509941 1699.80 3.96 37.34 3.19
19 18 539931 1799.77 8.07 40.10 6.09
20 19 569930 1899.75 4.51 51.68 4.00
21 20 599905 1999.61 10.44 43.14 7.12
22 21 629914 2099.71 5.53 43.97 4.45
23 22 659898 2199.67 5.74 44.67 4.24
24 23 689899 2299.66 6.34 49.92 5.65
25 24 719899 2399.65 11.37 54.05 8.06
26 25 749895 2499.63 8.07 54.66 5.78
27 26 779884 2599.59 8.45 50.14 7.29
28 27 809827 2699.31 15.97 59.55 8.63
29 28 734062 2446.83 5.45 37.98 10.68
30 29 869861 2899.54 12.20 58.46 8.84
31 30 784697 2615.19 6.37 38.34 11.19
32 31 818727 2728.72 3.71 35.82 8.43
33 32 632347 2106.63 41.77 1.71 33.16
34 33 674216 2246.32 47.19 1.60 28.58
35 34 606538 2021.69 1.06 2.03 35.14
36 35 719335 2396.51 47.68 1.58 26.97
37 36 590733 1969.06 1.13 2.27 39.42

View File

@ -0,0 +1,36 @@
cmake_minimum_required(VERSION 2.8.9)
# IncludeOS install location
if (NOT DEFINED ENV{INCLUDEOS_PREFIX})
set(ENV{INCLUDEOS_PREFIX} /usr/local)
endif()
include($ENV{INCLUDEOS_PREFIX}/includeos/pre.service.cmake)
project (DNS)
# Human-readable name of your service
set(SERVICE_NAME "CETIC DNS Service")
# Name of your service binary
set(BINARY "DNS")
# Source files to be linked with OS library parts to form bootable image
set(SOURCES
service.cpp # ...add more here
)
# To add your own include paths:
# set(LOCAL_INCLUDES ".")
# DRIVERS / PLUGINS:
set(DRIVERS
virtionet # Virtio networking
# virtioblock # Virtio block device
# ... Others from src/drivers
)
set(PLUGINS
)
# include service build script
include($ENV{INCLUDEOS_PREFIX}/includeos/post.service.cmake)

View File

@ -0,0 +1,7 @@
#!/bin/bash
mkdir -p build
pushd build
cmake ..
make
popd

View File

@ -0,0 +1,11 @@
{
"net": [
{
"iface": 0,
"config": "static",
"address": "192.168.122.100",
"netmask": "255.255.255.0",
"gateway": "192.168.122.1"
}
]
}

View File

@ -0,0 +1,262 @@
/**
* Basic DNS server for the IncludeOS unikernel framework.
*
* This code uses portions of code created by GitHub user tomasorti for his dns-server project (https://github.com/tomasorti/dns-server)
*/
#include <service>
#include <net/inet4>
#include <map>
#include <vector>
using namespace net;
#define SERVER_PORT 53
static const uint QR_MASK = 0x8000;
static const uint OPCODE_MASK = 0x7800;
static const uint AA_MASK = 0x0400;
static const uint TC_MASK = 0x0200;
static const uint RD_MASK = 0x0100;
static const uint RA_MASK = 0x8000;
static const uint RCODE_MASK = 0x000F;
static const uint HDR_OFFSET = 12;
static const int BUFFER_SIZE = 1024;
// for more info on DNS fields, see RFC 1035
struct queryHeader {
uint id; // 16 bit identifier assigned by the program who generated the query
uint query; // identifies if message is query (0) or a response (1)
uint opcode; // 4 bit field specifying kind of query: standard (0), inverse (1), server status request (2), reserved (3-15)
uint aa; // bit indicating if responding server is an authority for the domain name
uint truncation; // specifies whether this message was truncated or not
uint recursionDesired; // may be set in a query, directs the name server to pursue the query recursively
uint recursionAvailable; // set in a response, indicates whether recursive queries are available
uint responseCode; // 4 bit response code: 0 - no error, 1 - format error, 2 - server failure, 3 - name error, 4 - not implemented, 5 - refused
// unsigned 16-bit integers
uint questionCount; // number of entries in the question section
uint answerCount; // number of resource reconds in the answer section
uint nameServerCount; // number of name server resource records in the authority records section
uint additionalResourceCount; // number of resource records in the additional records section
};
struct queryQuestion {
std::string queryName; // domain name requested
uint queryType; // 2 octet code specifying the type of the query
uint queryClass; // 2 octet code specifying the class of the query
};
queryHeader pQueryHeader;
queryQuestion pQueryQuestion;
std::map<std::string,std::vector<int>> resourceRecords;
uint get16bits(const char*& buffer) {
uint value = static_cast<u_char> (buffer[0]);
value = value << 8;
value += static_cast<u_char> (buffer[1]);
buffer += 2;
return value;
}
void put8bits(char*& buffer, uint value) throw () {
buffer[0] = (value);
buffer += 1;
}
void put16bits(char*& buffer, uint value) throw () {
buffer[0] = (value & 0xFF00) >> 8;
buffer[1] = value & 0xFF;
buffer += 2;
}
void put32bits(char*& buffer, ulong value) throw () {
buffer[0] = (value & 0xFF000000) >> 24;
buffer[1] = (value & 0xFF0000) >> 16;
buffer[2] = (value & 0xFF00) >> 16;
buffer[3] = (value & 0xFF) >> 16;
buffer += 4;
}
queryHeader decodeHeader(const char* data, queryHeader pQueryHeader){
pQueryHeader.id = get16bits(data);
uint fields = get16bits(data);
pQueryHeader.query = fields & QR_MASK;
pQueryHeader.opcode = fields & OPCODE_MASK;
pQueryHeader.aa = fields & AA_MASK;
pQueryHeader.truncation = fields & TC_MASK;
pQueryHeader.recursionDesired = fields & RD_MASK;
pQueryHeader.recursionAvailable = fields & RA_MASK;
pQueryHeader.questionCount = get16bits(data);
pQueryHeader.answerCount = get16bits(data);
pQueryHeader.nameServerCount = get16bits(data);
pQueryHeader.additionalResourceCount = get16bits(data);
return pQueryHeader;
}
queryQuestion decodeQuery(const char*& data, queryQuestion pQueryQuestion){
pQueryQuestion.queryName = "";
int length = *data++;
while (length != 0) {
for (int i = 0; i < length; i++) {
char c = *data++;
pQueryQuestion.queryName.append(1, c);
}
length = *data++;
if (length != 0) pQueryQuestion.queryName.append(1,'.');
}
pQueryQuestion.queryType = get16bits(data);
pQueryQuestion.queryClass = get16bits(data);
return pQueryQuestion;
}
void codeDomain(char*& buffer, const std::string& domain) {
int start = 0, end; // indexes
while ((end = domain.find('.', start)) != std::string::npos) {
*buffer++ = end - start; // label length octet
for (int i=start; i<end; i++) {
*buffer++ = domain[i]; // label octets
}
start = end + 1; // Skip '.'
}
*buffer++ = domain.size() - start; // last label length octet
for (int i=start; i<domain.size(); i++) {
*buffer++ = domain[i]; // last label octets
}
*buffer++ = 0;
}
int processQuery(char* buffer, queryHeader pQueryHeader, queryQuestion pQueryQuestion){
// search for domain in resourceRecords
bool bRRexists = true;
std::map<std::string,std::vector<int>>::iterator record = resourceRecords.find(pQueryQuestion.queryName);
if (record == resourceRecords.end())
bRRexists = false;
char* bufferBegin = buffer;
// create header
put16bits(buffer, pQueryHeader.id);
int fields = (1 << 15); // Response code
fields += (0 << 11); // Opcode
fields += (0 << 10); // Authoritative code
fields += (0 << 9); // Truncated code
fields += (1 << 8); // Recursion desired code
fields += (0 << 7); // Recursion available code
fields += (0 << 6); // Z reserved code
fields += (0 << 5); // Answers authenticated code
fields += (0 << 4); // Non-authenticated data code
if(bRRexists)
fields += 0; // Reply code
else
fields += 3;
put16bits(buffer, fields);
put16bits(buffer, pQueryHeader.questionCount); // Questions count
if(bRRexists)
put16bits(buffer, 1); // Answers count
else
put16bits(buffer, 0);
put16bits(buffer, 0); // Authority RRs
put16bits(buffer, 0); // Additional RRs
// create domain query section - copy original question format
codeDomain(buffer, pQueryQuestion.queryName);
put16bits(buffer, pQueryQuestion.queryType);
put16bits(buffer, pQueryQuestion.queryClass);
// if requested domain exists in resourceRecords, create the answer
if(bRRexists){
// compression code to pointing to original question - should be offset from ID to domain name (in number of 16bits)
put16bits(buffer, 49164);
put16bits(buffer, pQueryQuestion.queryType);
put16bits(buffer, pQueryQuestion.queryClass);
put32bits(buffer, 0); // time to live
put16bits(buffer, 4); // data length (always 4 for IPv4 addresses)
put8bits(buffer,resourceRecords[pQueryQuestion.queryName][0]);
put8bits(buffer,resourceRecords[pQueryQuestion.queryName][1]);
put8bits(buffer,resourceRecords[pQueryQuestion.queryName][2]);
put8bits(buffer,resourceRecords[pQueryQuestion.queryName][3]);
}
int size = buffer - bufferBegin;
return size;
}
void Service::start()
{
resourceRecords["www.cetic.be"].push_back(10);
resourceRecords["www.cetic.be"].push_back(0);
resourceRecords["www.cetic.be"].push_back(0);
resourceRecords["www.cetic.be"].push_back(5);
resourceRecords["cetic.be"].push_back(10);
resourceRecords["cetic.be"].push_back(0);
resourceRecords["cetic.be"].push_back(0);
resourceRecords["cetic.be"].push_back(5);
resourceRecords["internship.cetic.be"].push_back(10);
resourceRecords["internship.cetic.be"].push_back(0);
resourceRecords["internship.cetic.be"].push_back(0);
resourceRecords["internship.cetic.be"].push_back(5);
// get the first network interfaces of the unikernel
auto& inet = Inet4::stack<0>();
Expects(inet.is_configured());
printf("Service IP address is %s\n", inet.ip_addr().str().c_str());
const UDP::port_t port = SERVER_PORT;
auto& sock = inet.udp().bind(port);
sock.on_read(
[&sock] (UDP::addr_t addr, UDP::port_t port, const char* data, size_t len){
pQueryHeader = decodeHeader(data, pQueryHeader);
data += HDR_OFFSET;
pQueryQuestion = decodeQuery(data, pQueryQuestion);
// debug output
printf("####### INCOMMING REQUEST #######\n");
printf("Getting UDP data from %s:%d\n", addr.str().c_str(), port);
printf("Header:\n");
printf("\tID: %u\n",pQueryHeader.id);
printf("\tQuery: %u\n", pQueryHeader.query);
printf("\topCode: %u\n", pQueryHeader.opcode);
printf("\tAA: %u\n", pQueryHeader.aa);
printf("\tTruncation: %u\n", pQueryHeader.truncation);
printf("\tRecursion Desired: %u\n", pQueryHeader.recursionDesired);
printf("\tRecursion Available: %u\n", pQueryHeader.recursionAvailable);
printf("\tReponse Code: %u\n", pQueryHeader.responseCode);
printf("\tQuestion Count: %u\n", pQueryHeader.questionCount);
printf("\tAnswer Count: %u\n", pQueryHeader.answerCount);
printf("\tName Server Count: %u\n", pQueryHeader.nameServerCount);
printf("\tAdditional Resource Count: %u\n", pQueryHeader.additionalResourceCount);
printf("Query:\n");
printf("\tQuery name: %s\n", pQueryQuestion.queryName.data());
printf("\tQuery Type: %u\n", pQueryQuestion.queryType);
printf("\tAdditional Resource Count: %u\n", pQueryQuestion.queryClass);
printf("#################################\n");
// send reply
char buffer[BUFFER_SIZE];
int nbrBytes = processQuery(buffer, pQueryHeader, pQueryQuestion);
sock.sendto(addr, port, buffer, nbrBytes);
});
INFO("DNS Server", "Listening on port %d\n", port);
}

View File

@ -0,0 +1,6 @@
{
"net" : [
{"device" : "virtio", "mac" : "c0:01:0a:00:00:2a"},
{"device" : "virtio", "mac" : "c0:01:0a:00:00:3a"}
]
}

View File

@ -0,0 +1,42 @@
cmake_minimum_required(VERSION 2.8.9)
if (NOT DEFINED ENV{INCLUDEOS_PREFIX})
set(ENV{INCLUDEOS_PREFIX} /usr/local)
endif()
include($ENV{INCLUDEOS_PREFIX}/includeos/pre.service.cmake)
project (WebServer)
# Human-readable name of your service
set(SERVICE_NAME "CETIC Unikernel Web Server")
# Name of your service binary
set(BINARY "WebServer")
# Source files to be linked with OS library parts to form bootable image
set(SOURCES
service.cpp # ...add more here
)
# To add your own include paths:
# set(LOCAL_INCLUDES ".")
# DRIVERS / PLUGINS:
set(DRIVERS
virtionet # Virtio networking
)
set(PLUGINS
autoconf
)
# STATIC LIBRARIES:
set(LIBRARIES
# path to full library
)
# include service build script
include($ENV{INCLUDEOS_PREFIX}/includeos/post.service.cmake)
# Create in-memory filesystem from folder
diskbuilder(disk)

View File

@ -0,0 +1,7 @@
#!/bin/bash
mkdir -p build
pushd build
cmake ..
make
popd

View File

@ -0,0 +1,13 @@
{
"net": [
{
"iface": 0,
"config": "static",
"address": "192.168.122.5",
"netmask": "255.255.255.0",
"gateway": "192.168.122.1"
}
]
}

View File

@ -0,0 +1,15 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>CETIC Internship Unikernel Web Page</title>
<link href="https://fonts.googleapis.com/css?family=Ubuntu:500,300" rel="stylesheet" type="text/css">
</head>
<body>
<h1 style="font-family: Arial, sans-serif">
CETIC Internship Unikernel Web Page
</h1>
<hr />
<p>This is the first web server spawn from a unikernel during the CETIC Intership 2017-18</p>
</body>
</html>

View File

@ -0,0 +1,47 @@
/*
* This code is adapted from the IncludeOS Acorn web server example.
*/
#include <service>
#include <net/inet4>
#include <net/http/server.hpp>
#include <memdisk>
std::unique_ptr<http::Server> server;
void Service::start()
{
// Retreive the stack (configured from outside)
auto& inet = net::Inet4::stack<0>();
Expects(inet.is_configured());
// Init the memdisk
auto& disk = fs::memdisk();
disk.init_fs([] (auto err, auto&) {
Expects(not err);
});
// Retreive the HTML page from the disk
auto file = disk.fs().read_file("/index.html");
Expects(file.is_valid());
net::tcp::buffer_t html(
new std::vector<uint8_t> (file.data(), file.data() + file.size()));
// Create a HTTP Server and setup request handling
server = std::make_unique<http::Server>(inet.tcp());
server->on_request([html] (auto req, auto rw)
{
// We only support get
if(req->method() != http::GET) {
rw->write_header(http::Not_Found);
return;
}
// Serve HTML on /
if(req->uri() == "/") {
rw->write(html);
} else {
rw->write_header(http::Not_Found);
}
});
// Start listening on port 80
server->listen(80);
}

View File

@ -0,0 +1,38 @@
#!/bin/bash
SRC_DIR=$HOME/unikernels
CONTAINERS=$SRC_DIR/SOURCE/CONTAINER
#IP=$(ip -4 route get 8.8.8.8 | awk {'print $7'} | tr -d '\n')
IP=10.65.0.101
PORT=53
source $SRC_DIR/BENCHMARKING/bench_unikernel_cleanup.sh
# build Docker containers
# 1 - compiler docker
pushd $CONTAINERS &&
docker build -t cetic/compiler . &&
popd &&
# 2 - individual dockers
pushd $CONTAINERS/DNS &&
docker run --rm -it -v "${PWD}":/usr/src/build -w /usr/src/build cetic/compiler g++ -std=c++11 -static -o runnableService *.cpp &&
docker build -t cetic/dns . &&
popd &&
# stopping all VMs and containers
docker stop $(docker ps -a -q)
virsh list | grep running | awk '{ print $2}' | while read DOMAIN; do
virsh destroy $DOMAIN
sleep 3
done
# launch docker containers
docker run --rm --cpus 1 -m 128m -d -p $IP:$PORT:$PORT/udp --name DNSBench cetic/dns &&
echo "#############################################################################" &&
echo "### ###" &&
echo "### Container DNS Server ready for benchmark. ###" &&
echo "### $IP:$PORT ###" &&
echo "### ###" &&
echo "#############################################################################"

View File

@ -0,0 +1,38 @@
#!/bin/bash
SRC_DIR=$HOME/unikernels
CONTAINERS=$SRC_DIR/SOURCE/CONTAINER
#IP=$(ip -4 route get 8.8.8.8 | awk {'print $7'} | tr -d '\n')
IP=10.65.0.101
PORT=80
source $SRC_DIR/BENCHMARKING/bench_unikernel_cleanup.sh
# build Docker containers
# 1 - compiler docker
pushd $CONTAINERS &&
docker build -t cetic/compiler . &&
popd &&
# 2 - individual dockers
pushd $CONTAINERS/WebServer &&
docker run --rm -it -v "${PWD}":/usr/src/build -w /usr/src/build cetic/compiler g++ -std=c++11 -static -o runnableService *.cpp &&
docker build -t cetic/webserver . &&
popd &&
# stopping all VMs and containers
docker stop $(docker ps -a -q)
virsh list | grep running | awk '{ print $2}' | while read DOMAIN; do
virsh destroy $DOMAIN
sleep 3
done
# launch docker containers
docker run --rm --cpus 1 -m 128m -d -p $IP:$PORT:$PORT --name WebServerBench cetic/webserver &&
echo "#############################################################################" &&
echo "### ###" &&
echo "### Container Web Server ready for benchmark. ###" &&
echo "### $IP:$PORT ###" &&
echo "### ###" &&
echo "#############################################################################"

View File

@ -0,0 +1,13 @@
#!/bin/bash
WEB_IP=192.168.122.5
DNS_IP=192.168.122.100
WEB_PORT=80
DNS_PORT=53
BRIDGE_INTERFACE=virbr0
sudo iptables -D FORWARD -o $BRIDGE_INTERFACE -d $DNS_IP -j ACCEPT
sudo iptables -t nat -D PREROUTING -p udp --dport $DNS_PORT -j DNAT --to $DNS_IP:$DNS_PORT
sudo iptables -D FORWARD -o $BRIDGE_INTERFACE -d $WEB_IP -j ACCEPT
sudo iptables -t nat -D PREROUTING -p tcp --dport $WEB_PORT -j DNAT --to $WEB_IP:$WEB_PORT

View File

@ -0,0 +1,55 @@
#!/bin/bash
SRC_DIR=$HOME/unikernels/BENCHMARKING
UNIKERNELS=$SRC_DIR/UNIKERNEL
HOST_IP=$(ip -4 route get 8.8.8.8 | awk {'print $7'} | tr -d '\n')
GUEST_IP=192.168.122.100
GUEST_PORT=53
HOST_PORT=53
BRIDGE_INTERFACE=virbr0
#write correct JSON file
pushd $UNIKERNELS/DNS &&
jq -n --arg IP_ADDRESS "$GUEST_IP" '{"net": [{"netmask": "255.255.255.0", "config": "static", "iface": 0, "gateway": "192.168.122.1", "address": $IP_ADDRESS}]}' > config.json &&
# build unikernels
sudo rm -rf build &&
mkdir -p build &&
pushd build &&
cmake .. &&
sudo make &&
popd &&
popd &&
# shuting down all VMs
docker stop $(docker ps -a -q)
virsh list | grep running | awk '{ print $2}' | while read DOMAIN; do
virsh destroy $DOMAIN
sleep 3
if [ "$DOMAIN" == "DNSBench" ]
then
virsh undefine $DOMAIN
fi
done
virsh undefine DNSBench
# launch unikernels in QEMU (+serial output to files)
virt-install \
--virt-type qemu --name DNSBench \
--vcpus 1 --ram 128 \
--import --disk $UNIKERNELS/DNS/build/DNS.img \
--serial file,path=/tmp/dns-benchmark.log \
--network network=default,model=virtio \
--check path_in_use=off \
--noautoconsole &&
# enable port-forwarding through iptables
source $SRC_DIR/bench_unikernel_cleanup.sh
sudo iptables -I FORWARD -o $BRIDGE_INTERFACE -d $GUEST_IP -j ACCEPT &&
sudo iptables -t nat -I PREROUTING -p udp --dport $HOST_PORT -j DNAT --to $GUEST_IP:$GUEST_PORT &&
echo "#############################################################################" &&
echo "### ###" &&
echo "### Unikernel DNS Server ready for benchmark. ###" &&
echo "### $HOST_IP:$HOST_PORT ###" &&
echo "### ###" &&
echo "#############################################################################"

View File

@ -0,0 +1,52 @@
#!/bin/bash
SRC_DIR=$HOME/unikernels/BENCHMARKING
UNIKERNELS=$SRC_DIR/UNIKERNEL
HOST_IP=$(ip -4 route get 8.8.8.8 | awk {'print $7'} | tr -d '\n')
GUEST_IP=192.168.122.5
GUEST_PORT=80
HOST_PORT=80
BRIDGE_INTERFACE=virbr0
# writing correct JSON file
pushd $UNIKERNELS/DNS &&
jq -n --arg IP_ADDRESS "$GUEST_IP" '{"net": [{"netmask": "255.255.255.0", "config": "static", "iface": 0, "gateway": "192.168.122.1", "address": $IP_ADDRESS}]}' > config.json &&
# build unikernels
sudo rm -rf build &&
mkdir -p build &&
pushd build &&
cmake .. &&
sudo make &&
popd &&
popd &&
# shuting down all VMs
docker stop $(docker ps -a -q)
virsh list | grep running | awk '{ print $2}' | while read DOMAIN; do
virsh destroy $DOMAIN
sleep 3
done
virsh undefine WebServerBench
# launch unikernels in QEMU (+serial output to files)
virt-install \
--virt-type qemu --name WebServerBench \
--vcpus 1 --ram 128 \
--import --disk $UNIKERNELS/WebServer/build/WebServer.img \
--serial file,path=/tmp/web-benchmark.log \
--network network=default,model=virtio \
--check path_in_use=off \
--noautoconsole &&
# enable port-forwarding through iptables
source $SRC_DIR/bench_unikernel_cleanup.sh
sudo iptables -I FORWARD -o $BRIDGE_INTERFACE -d $GUEST_IP -j ACCEPT &&
sudo iptables -t nat -I PREROUTING -p tcp --dport $HOST_PORT -j DNAT --to $GUEST_IP:$GUEST_PORT &&
echo "#############################################################################" &&
echo "### ###" &&
echo "### Unikernel Web Server ready for benchmark. ###" &&
echo "### $HOST_IP:$HOST_PORT ###" &&
echo "### ###" &&
echo "#############################################################################"

View File

@ -0,0 +1,30 @@
#!/bin/bash
# REMOVING IP TABLES RULES FOR UNIKERNEL BENCHMARKING
WEB_IP=192.168.122.5
DNS_IP=192.168.122.10
WEB_PORT=80
DNS_PORT=53
BRIDGE_INTERFACE=virbr0
sudo iptables -D FORWARD -o $BRIDGE_INTERFACE -d $DNS_IP -j ACCEPT
sudo iptables -t nat -D PREROUTING -p udp --dport $DNS_PORT -j DNAT --to $DNS_IP:$DNS_PORT
sudo iptables -D FORWARD -o $BRIDGE_INTERFACE -d $WEB_IP -j ACCEPT
sudo iptables -t nat -D PREROUTING -p tcp --dport $WEB_PORT -j DNAT --to $WEB_IP:$WEB_PORT
echo "This will stop and delete all VMs and Containers !"
read -p "Are you sure ? [Y|N] " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]
then
# STOPPING AND DELETING ALL CONTAINERS
docker stop $(docker ps -a -q)
docker rm $(docker ps -a -q)
virsh list | grep running | awk '{ print $2}' | while read DOMAIN; do
virsh destroy $DOMAIN
done
virsh list --all | grep "shut off" | awk '{ print $2}' | while read DOMAIN; do
virsh undefine $DOMAIN
done
fi

View File

@ -0,0 +1,67 @@
#!/usr/bin/python3
import sys
import subprocess
import shutil
import os.path
import csv
import time
RUN=1
TIME=300
CLIENTS=100
THREADS=4
QPS=100
QPS_INCREMENT=100
if __name__ == '__main__':
if len(sys.argv) < 2:
print("DNS Server Benchmarking Tool - CETIC Internship 2017/18 on Unikernels\n\tUsage: python3 dns_cont_benchmark.py [server_ip_address]")
sys.exit(1)
SVR_IP=sys.argv[1]
if shutil.which("dnsperf") is None:
print("ERROR: dnsperf is not installed, please run the install_bench_tools.sh script.")
sys.exit(1)
if os.path.isfile("dns_cont_benchmark.csv") is not True:
subprocess.run("touch dns_cont_benchmark.csv", stdout=subprocess.PIPE, shell=True)
with open("dns_cont_benchmark.csv", "w") as file:
writer = csv.writer(file)
writer.writerow(["TEST_RUN", "QUERIES_SENT", "QUERIES_COMPLETED", "QUERIES_LOST", "QUERIES_PER_SECOND", "AVG_LATENCY_SECONDS", "MIN", "MAX", "LATENCY_STD_DEV_SECONDS"])
while True:
print("########## LAUNCHING TEST " + str(RUN) + " ##########")
print("Queries per seconds: " + str(QPS)+ "\n")
# launch the dnsperf command
result = subprocess.run("dnsperf -s " + SVR_IP + " -d queryfile-example-current -l " + str(TIME) + " -T " + str(THREADS) + " -c " + str(CLIENTS) + " -Q " + str(QPS), stdout=subprocess.PIPE, shell=True)
#print(result.stdout.decode('utf-8'))
# convert output and store it in the csv file
list = result.stdout.decode("utf-8").split('\n')
for index in range(len(list)):
if list[index].startswith(" Queries sent:"):
queriesSent=list[index].split()[2]
queriesCompleted=list[index+1].split()[2]
queriesLost=list[index+2].split()[2]
queriesPerSecond=list[index+7].split()[3]
avgLatency=list[index+9].split()[3]
latencyMin=list[index+9].split()[5].replace(",", "")
latencyMax=list[index+9].split()[7].replace(")", "")
latencyStdDev=list[index+10].split()[3]
#print("TEST_RUN, QUERIES_SENT, QUERIES_COMPLETED, QUERIES_LOST, QUERIES_PER_SECOND, AVG_LATENCY_SECONDS, MIN, MAX, LATENCY_STD_DEV_SECONDS")
print("Queries sent:\t\t" + queriesSent + "\nQueries completed:\t" + queriesCompleted + "\nQueries Lost:\t\t" + queriesLost + \
"\nQueries per second:\t" + queriesPerSecond + "\nAverage latency:\t" + avgLatency + "\nMinimum latency:\t" + latencyMin + \
"\nMax latency:\t\t" + latencyMax + "\nLatency Std Dev:\t" + latencyStdDev)
with open("dns_cont_benchmark.csv", "a") as file:
writer = csv.writer(file)
writer.writerow([RUN, queriesSent, queriesCompleted, queriesLost, queriesPerSecond, avgLatency, latencyMin, latencyMax, latencyStdDev])
break
print("########## TEST " + str(RUN) + " COMPLETE ##########\n")
# increase the TEST_RUN value and increment the number of queries per second
RUN=RUN+1
QPS=QPS+QPS_INCREMENT
# sleep for 30 seconds between tests
time.sleep(30)

View File

@ -0,0 +1,67 @@
#!/usr/bin/python3
import sys
import subprocess
import shutil
import os.path
import csv
import time
RUN=1
TIME=300
CLIENTS=100
THREADS=4
QPS=100
QPS_INCREMENT=100
if __name__ == '__main__':
if len(sys.argv) < 2:
print("DNS Server Benchmarking Tool - CETIC Internship 2017/18 on Unikernels\n\tUsage: python3 dns_unik_benchmark.py [server_ip_address]")
sys.exit(1)
SVR_IP=sys.argv[1]
if shutil.which("dnsperf") is None:
print("ERROR: dnsperf is not installed, please run the install_bench_tools.sh script.")
sys.exit(1)
if os.path.isfile("dns_unik_benchmark.csv") is not True:
subprocess.run("touch dns_unik_benchmark.csv", stdout=subprocess.PIPE, shell=True)
with open("dns_unik_benchmark.csv", "w") as file:
writer = csv.writer(file)
writer.writerow(["TEST_RUN", "QUERIES_SENT", "QUERIES_COMPLETED", "QUERIES_LOST", "QUERIES_PER_SECOND", "AVG_LATENCY_SECONDS", "MIN", "MAX", "LATENCY_STD_DEV_SECONDS"])
while True:
print("########## LAUNCHING TEST " + str(RUN) + " ##########")
print("Queries per seconds: " + str(QPS)+ "\n")
# launch the dnsperf command
result = subprocess.run("dnsperf -s " + SVR_IP + " -d queryfile-example-current -l " + str(TIME) + " -T " + str(THREADS) + " -c " + str(CLIENTS) + " -Q " + str(QPS), stdout=subprocess.PIPE, shell=True)
#print(result.stdout.decode('utf-8'))
# convert output and store it in the csv file
list = result.stdout.decode("utf-8").split('\n')
for index in range(len(list)):
if list[index].startswith(" Queries sent:"):
queriesSent=list[index].split()[2]
queriesCompleted=list[index+1].split()[2]
queriesLost=list[index+2].split()[2]
queriesPerSecond=list[index+7].split()[3]
avgLatency=list[index+9].split()[3]
latencyMin=list[index+9].split()[5].replace(",", "")
latencyMax=list[index+9].split()[7].replace(")", "")
latencyStdDev=list[index+10].split()[3]
#print("TEST_RUN, QUERIES_SENT, QUERIES_COMPLETED, QUERIES_LOST, QUERIES_PER_SECOND, AVG_LATENCY_SECONDS, MIN, MAX, LATENCY_STD_DEV_SECONDS")
print("Queries sent:\t\t" + queriesSent + "\nQueries completed:\t" + queriesCompleted + "\nQueries Lost:\t\t" + queriesLost + \
"\nQueries per second:\t" + queriesPerSecond + "\nAverage latency:\t" + avgLatency + "\nMinimum latency:\t" + latencyMin + \
"\nMax latency:\t\t" + latencyMax + "\nLatency Std Dev:\t" + latencyStdDev)
with open("dns_unik_benchmark.csv", "a") as file:
writer = csv.writer(file)
writer.writerow([RUN, queriesSent, queriesCompleted, queriesLost, queriesPerSecond, avgLatency, latencyMin, latencyMax, latencyStdDev])
break
print("########## TEST " + str(RUN) + " COMPLETE ##########\n")
# increase the TEST_RUN value and increment the number of queries per second
RUN=RUN+1
QPS=QPS+QPS_INCREMENT
# sleep for 30 seconds between tests
time.sleep(30)

View File

@ -0,0 +1,24 @@
#!/bin/bash
SRC_DIR=$HOME/unikernels/BENCHMARKING
# DNSPerf
sudo apt-get install -y libbind-dev libkrb5-dev libssl-dev libcap-dev libxml2-dev libgeoip-dev bind9utils make &&
wget ftp://ftp.nominum.com/pub/nominum/dnsperf/2.1.0.0/dnsperf-src-2.1.0.0-1.tar.gz &&
tar xzvf dnsperf-src-2.1.0.0-1.tar.gz &&
pushd dnsperf-src-2.1.0.0-1 &&
./configure &&
make &&
sudo make install &&
popd &&
wget ftp://ftp.nominum.com/pub/nominum/dnsperf/data/queryfile-example-current.gz &&
gunzip queryfile-example-current.gz &&
#Usage: dnsperf -s 10.0.0.100 -d queryfile-example-current -l 60 -c 1 -Q 10
#wrk2 install
git clone https://github.com/giltene/wrk2 &&
pushd wrk2 &&
sudo make &&
sudo cp wrk /usr/local/bin/wrk2 &&
popd
#Usage: wrk2 -d 5m -R 100 http://10.0.0.5/

View File

@ -0,0 +1,94 @@
#!/usr/bin/python3
import sys
import subprocess
import os.path
import csv
import json
import time
import _thread
import os
import datetime as datetime
import random
BENCHMARK_TIME_SECONDS=60*20
MAX_NBR_VMS=150
NBR_VMS_INCREMENT=10
GUESTS=dict()
NBR_VMS=0
def run_cmd(COMMAND):
return subprocess.run(COMMAND, stdout=subprocess.PIPE, shell=True)
def timeGuestStart(GUEST):
response = 1
startTime=datetime.datetime.now()
while response is not 0:
response = os.system("ping -c 1 " + GUESTS[GUEST] + "> /dev/null 2>&1")
endTime=datetime.datetime.now()
bootTime=(endTime-startTime).microseconds
with open("startup_cont_benchmark.csv", "a") as file:
writer = csv.writer(file)
writer.writerow([NBR_VMS, GUEST, (bootTime/1000000)])
if __name__ == '__main__':
if len(sys.argv) < 2:
print("Application Startup Benchmarking Tool - CETIC Internship 2017/18 on Unikernels\n\tUsage: python3 startup_cont_benchmark.py [nbr of VMs]")
sys.exit(1)
NBR_VMS=int(sys.argv[1])
if os.path.isfile("startup_cont_benchmark.csv") is not True:
subprocess.run("touch startup_cont_benchmark.csv", stdout=subprocess.PIPE, shell=True)
with open("startup_cont_benchmark.csv", "w") as file:
writer = csv.writer(file)
writer.writerow(["NBR_OF_GUESTS", "GUEST_STOPPED", "STARTUP_TIME_SECONDS"])
while NBR_VMS < MAX_NBR_VMS:
print("### STOPPING PREVIOUS VMS")
# stop all running VMs
run_cmd("docker stop $(docker ps -a -q) 2> /dev/null")
run_cmd("virsh list | grep running | awk '{ print $2}' | while read DOMAIN; do virsh destroy $DOMAIN; sleep 3; virsh undefine $DOMAIN; done")
run_cmd("docker ps -a -q | while read DOMAIN; do docker rm $DOMAIN; done")
# create table of guest VMs
GUESTS.clear()
i = 10
for x in range(int(NBR_VMS)):
GUESTS[("VM_"+str(x))] = ("172.18.0." + str(i))
i = i+1
print("### BUILDING CONTAINERS")
run_cmd("cd ../SOURCE/CONTAINER && docker build -t cetic/compiler .")
run_cmd("cd ../SOURCE/CONTAINER/DNS &&\
docker run --rm -it -v $PWD:/usr/src/build -w /usr/src/build cetic/compiler g++ -std=c++11 -static -o runnableService *.cpp &&\
docker build -t cetic/dns .")
run_cmd("docker network create --subnet=172.18.0.0/16 --driver=bridge bench_net 2> /dev/null")
print("### LAUNCHING CONTAINERS")
# create and launch each VM
for key, value in GUESTS.items():
# for each entry in GUESTS build the unikernel and move the img to another folder
run_cmd("docker run --cpus 1 -m 128m -d --ip " + value + " --network=bench_net --name " + key + " cetic/dns 2> /dev/null")
print("### LAUNCHING BENCHMARK FOR " + str(BENCHMARK_TIME_SECONDS) + " SECONDS")
timeout=time.time() + BENCHMARK_TIME_SECONDS
while time.time() <= timeout:
# stop a VM
RANDOM_GUEST="VM_"+str(random.randint(0, (int(NBR_VMS)-1)))
run_cmd("docker stop " + RANDOM_GUEST)
print(RANDOM_GUEST + " shut down")
# launch a thread to start a VM
_thread.start_new_thread(run_cmd, ("docker start " + RANDOM_GUEST, ))
# launch another thread to time boot time
_thread.start_new_thread(timeGuestStart, (RANDOM_GUEST, ))
print(RANDOM_GUEST + " started...")
time.sleep(5)
#increment number of VMs for next test
NBR_VMS=NBR_VMS+NBR_VMS_INCREMENT
run_cmd("docker stop $(docker ps -a -q) 2> /dev/null")

View File

@ -0,0 +1,118 @@
#!/usr/bin/python3
import sys
import subprocess
import os.path
import csv
import json
import time
import _thread
import os
import datetime as datetime
import random
BENCHMARK_TIME_SECONDS=60*20
MAX_NBR_VMS=150
NBR_VMS_INCREMENT=10
GUESTS=dict()
NBR_VMS=0
def run_cmd(COMMAND):
return subprocess.run(COMMAND, stdout=subprocess.PIPE, shell=True)
def timeGuestStart(GUEST):
response = 1
startTime=datetime.datetime.now()
while response is not 0:
response = os.system("ping -c 1 " + GUESTS[GUEST] + "> /dev/null 2>&1")
endTime=datetime.datetime.now()
bootTime=(endTime-startTime).microseconds
with open("startup_unik_benchmark.csv", "a") as file:
writer = csv.writer(file)
writer.writerow([NBR_VMS, GUEST, (bootTime/1000000)])
if __name__ == '__main__':
if len(sys.argv) < 2:
print("Application Startup Benchmarking Tool - CETIC Internship 2017/18 on Unikernels\n\tUsage: python3 startup_unik_benchmark.py [nbr of VMs]")
sys.exit(1)
NBR_VMS=int(sys.argv[1])
if os.path.isfile("startup_unik_benchmark.csv") is not True:
subprocess.run("touch startup_unik_benchmark.csv", stdout=subprocess.PIPE, shell=True)
with open("startup_unik_benchmark.csv", "w") as file:
writer = csv.writer(file)
writer.writerow(["NBR_OF_GUESTS", "GUEST_STOPPED", "STARTUP_TIME_SECONDS"])
while NBR_VMS < MAX_NBR_VMS:
print("### STOPPING PREVIOUS VMS")
# stop all running VMs
run_cmd("docker stop $(docker ps -a -q) 2> /dev/null")
run_cmd("virsh list | grep running | awk '{ print $2}' | while read DOMAIN; do virsh destroy $DOMAIN; sleep 3; done")
run_cmd("virsh list --all | grep VM_ | awk '{ print $2}' | while read DOMAIN; do virsh undefine $DOMAIN; sleep 3; done")
# create table of guest VMs
GUESTS.clear()
i = 10
for x in range(int(NBR_VMS)):
GUESTS[("VM_"+str(x))] = ("192.168.122." + str(i))
i = i+1
#print(GUESTS)
run_cmd("sudo rm -rf GUESTS; mkdir GUESTS")
# create and launch each VM
print("### BUILDING UNIKERNEL IMAGES")
for key, value in GUESTS.items():
# modify config.json with the IP address
data = {}
data["net"] = []
data["net"].append({
"iface": 0,
"config": "static",
"address": value ,
"netmask": "255.255.255.0",
"gateway": "192.168.122.1"
})
with open("UNIKERNEL/DNS/config.json", "w") as outfile:
json.dump(data, outfile)
# for each entry in GUESTS build the unikernel and move the img to another folder
run_cmd("cd UNIKERNEL/DNS && sudo rm -rf build && mkdir -p build && cd build && cmake .. && sudo make 2> /dev/null")
run_cmd(("sudo mv UNIKERNEL/DNS/build/DNS.img GUESTS/" + key + ".img"))
run_cmd(("virt-install \
--virt-type qemu --name " + key + " \
--vcpus 1 --ram 128 \
--import --disk GUESTS/" + key +".img \
--serial file,path=/tmp/" + key + ".log \
--network network=default,model=virtio \
--check path_in_use=off \
--noautoconsole"))
print(" - " + key + " built")
print("### LAUNCHING BENCHMARK FOR " + str(BENCHMARK_TIME_SECONDS) + " SECONDS")
timeout = time.time() + BENCHMARK_TIME_SECONDS
while time.time() <= timeout:
# TODO loop for a predetermined number of time
# TODO stop a random VM, restart it, time its boot time
# stop a VM
RANDOM_GUEST="VM_"+str(random.randint(0, (int(NBR_VMS)-1)))
run_cmd("virsh destroy " + RANDOM_GUEST)
print(RANDOM_GUEST + " shut down")
# launch a thread to start a VM
_thread.start_new_thread(run_cmd, ("virsh start " + RANDOM_GUEST, ))
# launch another thread to time boot time
_thread.start_new_thread(timeGuestStart, (RANDOM_GUEST, ))
print(RANDOM_GUEST + " started...")
time.sleep(5)
#increment number of VMs for next test
NBR_VMS=NBR_VMS+NBR_VMS_INCREMENT
# cleanup test bed
run_cmd("virsh list --all | grep VM_ | awk '{ print $2}' | while read DOMAIN; do virsh destroy $DOMAIN; sleep 3; virsh undefine $DOMAIN; done")
run_cmd("sudo rm -rf GUESTS")

View File

@ -0,0 +1,64 @@
#!/usr/bin/python3
import sys
import subprocess
import shutil
import os.path
import csv
import time
import string
RUN=1
TIME=300
CONNECTIONS=100
THREADS=4
QPS=100
QPS_INCREMENT=100
if __name__ == '__main__':
if len(sys.argv) < 2:
print("DNS Server Benchmarking Tool - CETIC Internship 2017/18 on Unikernels\n\tUsage: python3 web_cont_benchmark.py [server_ip_address]")
sys.exit(1)
SVR_IP=sys.argv[1]
if shutil.which("dnsperf") is None:
print("ERROR: dnsperf is not installed, please run the install_bench_tools.sh script.")
sys.exit(1)
if os.path.isfile("web_cont_benchmark.csv") is not True:
subprocess.run("touch web_cont_benchmark.csv", stdout=subprocess.PIPE, shell=True)
with open("web_cont_benchmark.csv", "w") as file:
writer = csv.writer(file)
writer.writerow(["TEST_RUN", "QUERIES_SENT", "QUERIES_PER_SECOND", "AVG_LATENCY_MILLISECONDS", "MAX_LATENCY_MILLISECONDS", "LATENCY_STD_DEV_PERCENT"])
while True:
print("########## LAUNCHING TEST " + str(RUN) + " ##########")
print("Queries per seconds: " + str(QPS))
# launch the dnsperf command
result = subprocess.run("wrk2 -t " + str(THREADS) + " -d " + str(TIME) + "s -c " + str(CONNECTIONS) + " -R " + str(QPS) + " http://" + SVR_IP + "/", stdout=subprocess.PIPE, shell=True)
#print(result.stdout.decode('utf-8'))
# convert output and store it in the csv file
list = result.stdout.decode("utf-8").split('\n')
for index in range(len(list)):
if list[index].startswith(" Latency"):
avgLatency=list[index].split()[1].strip(string.ascii_letters)
latencyMax=list[index].split()[3].strip(string.ascii_letters)
latencyStdDev=list[index].split()[2].strip(string.ascii_letters)
queriesSent=list[index+2].split()[0]
queriesPerSecond=list[index+3].split()[1]
print("Queries sent:\t\t" + queriesSent + "\nQueries per second:\t" + queriesPerSecond + "\nAverage latency:\t" + avgLatency + "ms" + \
"\nMax latency:\t\t" + latencyMax + "ms" + "\nLatency Std Dev:\t" + latencyStdDev + "ms")
with open("web_cont_benchmark.csv", "a") as file:
writer = csv.writer(file)
writer.writerow([RUN, queriesSent, queriesPerSecond, avgLatency, latencyMax, latencyStdDev])
break
print("########## TEST " + str(RUN) + " COMPLETE ##########\n")
# increase the TEST_RUN value and increment the number of queries per second
RUN=RUN+1
QPS=QPS+QPS_INCREMENT
# sleep for 30 seconds between tests
time.sleep(30)

View File

@ -0,0 +1,64 @@
#!/usr/bin/python3
import sys
import subprocess
import shutil
import os.path
import csv
import time
import string
RUN=1
TIME=300
CONNECTIONS=100
THREADS=4
QPS=100
QPS_INCREMENT=100
if __name__ == '__main__':
if len(sys.argv) < 2:
print("DNS Server Benchmarking Tool - CETIC Internship 2017/18 on Unikernels\n\tUsage: python3 web_unik_benchmark.py [server_ip_address]")
sys.exit(1)
SVR_IP=sys.argv[1]
if shutil.which("dnsperf") is None:
print("ERROR: dnsperf is not installed, please run the install_bench_tools.sh script.")
sys.exit(1)
if os.path.isfile("web_unik_benchmark.csv") is not True:
subprocess.run("touch web_unik_benchmark.csv", stdout=subprocess.PIPE, shell=True)
with open("web_unik_benchmark.csv", "w") as file:
writer = csv.writer(file)
writer.writerow(["TEST_RUN", "QUERIES_SENT", "QUERIES_PER_SECOND", "AVG_LATENCY_MILLISECONDS", "MAX_LATENCY_MILLISECONDS", "LATENCY_STD_DEV_PERCENT"])
while True:
print("########## LAUNCHING TEST " + str(RUN) + " ##########")
print("Queries per seconds: " + str(QPS))
# launch the dnsperf command
result = subprocess.run("wrk2 -t " + str(THREADS) + " -d " + str(TIME) + "s -c " + str(CONNECTIONS) + " -R " + str(QPS) + " http://" + SVR_IP + "/", stdout=subprocess.PIPE, shell=True)
#print(result.stdout.decode('utf-8'))
# convert output and store it in the csv file
list = result.stdout.decode("utf-8").split('\n')
for index in range(len(list)):
if list[index].startswith(" Latency"):
avgLatency=list[index].split()[1].strip(string.ascii_letters)
latencyMax=list[index].split()[3].strip(string.ascii_letters)
latencyStdDev=list[index].split()[2].strip(string.ascii_letters)
queriesSent=list[index+2].split()[0]
queriesPerSecond=list[index+3].split()[1]
print("Queries sent:\t\t" + queriesSent + "\nQueries per second:\t" + queriesPerSecond + "\nAverage latency:\t" + avgLatency + "ms" + \
"\nMax latency:\t\t" + latencyMax + "ms" + "\nLatency Std Dev:\t" + latencyStdDev + "ms")
with open("web_unik_benchmark.csv", "a") as file:
writer = csv.writer(file)
writer.writerow([RUN, queriesSent, queriesPerSecond, avgLatency, latencyMax, latencyStdDev])
break
print("########## TEST " + str(RUN) + " COMPLETE ##########\n")
# increase the TEST_RUN value and increment the number of queries per second
RUN=RUN+1
QPS=QPS+QPS_INCREMENT
# sleep for 30 seconds between tests
time.sleep(30)

54
DEPLOYMENT/README.md Normal file
View File

@ -0,0 +1,54 @@
# Deployment
This folder contains the files to deploy the proof of concept environment.
## pre_deployment_installation.sh
Installs all the required components to launch both the unikernel and the container environment.
Install includes:
* IncludeOS project installation
* libvirt for unikernel virtual machines deployment
* Docker CE for container deployments
**NOTE:** installation of the Docker CE adds the current user to the docker group, you must logout/login for the changes to take effect.
## deploy_unikernels.sh
This script will deploy the unikernels by taking the following steps:
* building the unikernels from the source code (in the SOURCE directory)
* create the QEMU networks for the unikernels virtual machine
* create and launch the virtual machines in their respective networks
The networks are created with the following addressing:
![Proof of concept network addressing scheme](https://git.cetic.be/stages/unikernels/raw/feature/stagelongree2018/MEDIA/unikernel_network.PNG "Proof of concept network addressing scheme")
| VM | IP Address |
| ----------- |-----------------|
| Firewall | 192.168.100.254 |
| Firewall | 192.168.101.3 |
| Router | 192.168.101.2 |
| Router | 10.0.0.254 |
| Web server | 10.0.0.5 |
| DNS server | 10.0.0.100 |
The current proof of concept environment and is self contained. It is not possible to directly connect the firewall to the external network.
It is possible to contact the DNS and the web server through iptables rules (examples in the benchmark launching scripts).
## deploy_containers.sh
This script will deploy the containers (using ported code from the unikernel versions) by taking the following steps:
* building the compiler image
* running the compiler image to cross-compile the application
* build the application container using the compiled application program
* run the container images built in the previous step
The container ports are mapped as follows:
| Container | Host Port | Guest Port |
| ----------- | ---------- | ---------- |
| Web server | 80/tcp | 80/tcp |
| DNS server | 53/udp | 53/udp |
**NOTE:** due to time constraints during the project, the firewall and router applications were not ported to containers.

View File

@ -0,0 +1,43 @@
#!/bin/bash
#NB: due to time constraint, only the DNS and WebServer analogs
# have code ported from the Unikernel application.
# Additionally the container ports are bound to the host's
# IP address for benchmarking.
SRC_DIR=$HOME/unikernels
CONTAINERS=$SRC_DIR/SOURCE/CONTAINER
# exposes the interface with internet connectivity for benchmarking
# if your benchmarking device is on another network, adjust accordingly
IP=$(ip -4 route get 8.8.8.8 | awk {'print $7'} | tr -d '\n')
DNS_PORT=53
WEB_PORT=80
# build Docker containers
# 1 - compiler docker
pushd $CONTAINERS &&
docker build -t cetic/compiler . &&
popd &&
# 2 - individual dockers
pushd $CONTAINERS/DNS &&
docker run --rm -it -v "${PWD}":/usr/src/build -w /usr/src/build cetic/compiler g++ -std=c++11 -static -o runnableService *.cpp &&
docker build -t cetic/dns . &&
popd &&
pushd $CONTAINERS/WebServer &&
docker run --rm -it -v "${PWD}":/usr/src/build -w /usr/src/build cetic/compiler g++ -std=c++11 -static -o runnableService *.cpp &&
docker build -t cetic/webserver . &&
popd &&
# launch docker containers
docker run --rm --cpuset-cpus 1 -m 128m -d -p $IP:$DNS_PORT:$DNS_PORT/udp --name DNS cetic/dns
docker run --rm --cpuset-cpus 1 -m 128m -d -p $IP:$WEB_PORT:$WEB_PORT --name WebServer cetic/webserver
echo "#############################################################################"
echo "### ###"
echo "### Containers successfully launched. ###"
echo "### Web server accessible on port $WEB_PORT. ###"
echo "### DNS server accessible on port $DNS_PORT. ###"
echo "### ###"
echo "#############################################################################"

View File

@ -0,0 +1,93 @@
#!/bin/bash
# NB: This script assumes you cloned the project into you HOME directory.
# If this is not the case, change the following variables accordingly
SRC_DIR=$HOME/unikernels
UNIKERELS=$SRC_DIR/SOURCE/UNIKERNEL
# build unikernels
pushd $UNIKERELS/DNS &&\
mkdir -p build &&\
pushd build &&\
cmake .. &&\
make &&\
popd &&\
pushd $UNIKERELS/WebServer &&\
mkdir -p build &&\
pushd build &&\
cmake .. &&\
sudo make &&\
popd &&\
pushd $UNIKERELS/Router &&\
mkdir -p build &&\
pushd build &&\
cmake .. &&\
make &&\
popd &&\
pushd $UNIKERELS/Firewall &&\
mkdir -p build &&\
pushd build &&\
cmake .. &&\
make &&\
popd &&\
# configure networks for QEMU
# remove default bridge created
sudo ip link del bridge43
# create the bridge interfaces
virsh net-define --file $UNIKERELS/internal.xml &&
virsh net-define --file $UNIKERELS/external.xml &&
virsh net-define --file $UNIKERELS/firewall.xml &&
virsh net-start internal &&
virsh net-start external &&
virsh net-start firewall &&
virsh net-autostart internal &&
virsh net-autostart external &&
virsh net-autostart firewall &&
# launch unikernels in QEMU (+serial output to files)
virt-install \
--virt-type qemu --name DNS \
--vcpus 1 --ram 128 \
--import --disk $UNIKERELS/DNS/build/DNS.img \
--serial file,path=/tmp/dns.log \
--network network=internal,model=virtio \
--noautoconsole &&
virt-install \
--virt-type qemu --name WebServer \
--vcpus 1 --ram 128 \
--import --disk $UNIKERELS/WebServer/build/WebServer.img \
--serial file,path=/tmp/web.log \
--network network=internal,model=virtio \
--noautoconsole &&
virt-install \
--virt-type qemu --name Router \
--vcpus 1 --ram 128 \
--import --disk $UNIKERELS/Router/build/Router.img \
--serial file,path=/tmp/router.log \
--network network=internal,model=virtio \
--network network=firewall,model=virtio \
--noautoconsole &&
virt-install \
--virt-type qemu --name Firewall \
--vcpus 1 --ram 128 \
--import --disk $UNIKERELS/Firewall/build/Firewall.img \
--serial file,path=/tmp/firewall.log \
--network network=external,model=virtio \
--network network=firewall,model=virtio \
--noautoconsole &&
echo "#############################################################################"
echo "### ###"
echo "### Unikernels successfully launched. ###"
echo "### Serial outputs are located in /tmp. ###"
echo "### ###"
echo "#############################################################################"

View File

@ -0,0 +1,30 @@
#!/bin/bash
sudo apt-get update &&
sudo apt-get install -y git &&
# install IncludeOS
pushd $HOME &&
git clone --recurse-submodules https://github.com/hioa-cs/IncludeOS &&
popd &&
pushd $HOME/IncludeOS &&
sudo ./install.sh -y &&
popd &&
# install libvirt
sudo apt-get install -y libvirt-bin virtinst &&
#NB: requires logout/login to take effect
sudo usermod -a -G libvirtd $USER &&
# install Docker
sudo apt-get install -y apt-transport-https ca-certificates curl software-properties-common &&
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - &&
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" &&
sudo apt-get update &&
sudo apt-get install -y docker-ce &&
sudo usermod -a -G docker $USER &&
echo "#############################################################################"
echo "### ###"
echo "### /!\ You must logout/login to apply changes before continuing. /!\ ###"
echo "### ###"
echo "#############################################################################"

BIN
MEDIA/Benchmark 2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
MEDIA/Benchmark.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

1
MEDIA/Benchmark.xml Normal file
View File

@ -0,0 +1 @@
<mxfile userAgent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36" version="8.6.1" editor="www.draw.io" type="device"><diagram id="9f6e7cca-04d0-9da1-074d-84f045bb2cb3" name="Performance/Resilience">7VhNc5swEP01XDOAALtH23XSQzqTGR96lkEBNYL1iMUf/fWVQJjv2J0mmTQNB0a8XYF4b9/yYZFVeryTdJd8h4gJy7Wjo0W+Wq77xZurvQZOFeB7bgXEkkcVZDfAhv9iFejUaMEjlhusghBAIN91wRCyjIXYwaiUcOimPYKIOsCOxmwAbEIqhugPHmFSoXPfbvBvjMdJfWXHNpEtDZ9iCUVmrme55LHcqnBK63OZ/DyhERxaEFlbZCUBsBqlxxUTmtoubbcT0fO6JcvwmgmkmrCnomD1ist14anmorwbpvNtiywPCUe22dFQRw9KfIUlmAp15KjhIxdiBQJkOZfclpvCh+syS90ziezYgsw67xikDOVJpdTRueHM1BSpOT80Cjm1QklLHfeLAampivh87oYZNTDkjBPlDYjaMLnnigbX1iMmB8QpbXd6mB5jbZKbkOch3ORlcn6jmGLVuMtgRPPkzHaPztl6Eaw1nqOEJzZGdBWpi1bRudQMc1Xa93TLxAPkHDlkKrYFREhbCQvBYx1A0KJCgYJn6hq1w+yXkdF3uzJ69mwg45iKQfD3IjrD6maRMr45BIkJxJBRsW7QtjY/GeLJdCtaIGiaznPuQfNW5g3kscttVJ6wUDUQmYmT/OZQyNAs2TcNkcqYYac69c08q4FkgiLfd7vcGKPl1IWU9NRK2AHPMG+d+UEDjbSe3ZPW6TWfS/me3VOzWkGj7flWrpLbH3h2zyUWVOeEgmuOpzxbpGIRopbvsn+EDizPjb8lu2n9UxZrVdZ0xbRbQAYZexkXurNeM50PmykZc+ELtFIn+AguDN6tC72utD7xn3eh97ouDD5deK0Lfdt/Oxd6H8GFs3/FhcS/8Cx8ZRfOPl046UKnJ5X7hs9C/yO4cP5uXdh/w5xdeBa+8hvp/NOF17rQ897wWTjUZcmyMEmpfGp93wdCXXO51aMYz3f9P3zxD2QcEXv6x03/LYcMlR394vf/WFl12Pw7q/zZ/J8k698=</diagram><diagram id="6d5bb729-f55c-c8ed-69e5-837c886226c1" name="Orchestration">5ZrNk6MqEMD/mhyTUvErx8lksnt4r95W5bDHKUZJpAbFQvIx769fUEhCMDtuVcZsaQ5RG0T8dYPdDRPwnB+/MVhm/9IUkYnnpMcJWE48b+7H4l8KPhpB4HuNYMtw2oics2CN/0eN0NXSHU5RpWSNiFNKOC5NYUKLAiXckEHG6MGstqEkNQQl3CKjG1KwTiBBVrWfOOVZI42Di9rfEd5m+smuo0reYPK+ZXRXqOdNPLCpf01xDnVbqn6VwZQeLkTgZQKeGaW8OcuPz4hItCa21Y3SU78ZKniXG5Ra9pDskO5x3S/+oVnUb4NkfWcCFocMc7QuYSJLD0L5QpbxnIgrV5xWnNF39EwJZfXdwKl/omSDCdHyghbi9oXdWdX/PWIcHS9EqvPfEM0RZx+iiio9gVSGBoC6PpzVBrRVZRcq83RFqExle2r7jEucKGLt9MDn9E4KlgxSWGUnkjepKTrizlI2kh+3cozN8iqBaJYQuktnFWJ7nKBXoYf32pQNvDX2KF5Gd2IcXTEObca+byMO7kDYHwVhEMQPIxyMg7DrG4T9wOuNcDgKwr7jPYxwNA7CfviwWSK2CK+bV5d1iorDoj51Le7i3XgHyC3eASR4W4jLRBBDQr6QpLDw0Z5UQY7TVD6m1ScxvZZ7fAWDyLRv16YftTga9/Az5t3o21Y/GPpAm5YOKBx7dvkq+lrRn+EHA8bvBw8zftftht8fMP54/jjrt0PEVvzBcPH7ADzO+u0YU+IXVAaL24rpna4x/T14d4s4a49wl5MlkpA/uiZGdDIpbleElT1ZrVT25B6TiGt+Qtsc9KCF6j3cR7dDlPlX55nCyJwC+s0zueMIISPvCnKPAY47jhgyvpoEekVsB5FDRByFV4Fij4kQ144Uh4g4DoKHIfbsaHCQiOdmyNHnROF1jPgGnG2KXNMH7jPk0AY94nRTFJjLBX0G3C2rimNLN0Vzcz2sV+u3A8CxpZtivVvjEdZvR4pjSzfFsbnO06v125Hm0NNNVmjfZ7qpZWHNIq3x/APfEPlBK8wxlZjeKOc0b+HH6W+TT16Ln9lsmvKao3RaJQxnFspTycmXsAvKk0yB/5o0SxBeuT2erYv5F+WoQDfHvsa2Iej4pFChIlWny4TAqsKJCf/KSQdgtQLgpv9vaeomVZTqPWw3mHbM6zFEIMd7ZDTeBlI94QfFoifnb/XV2oSvv926iYruWILUXWd1fN5QEJoNcci2iFsN1Xo9vXY3VdsBxk1V47yJtS402j7ePh2mRBYsThsEL2xCbREEi/phT1XZ7GmU4wzqiw0+yllvofqzzDiXmyGfJAdvlaSFN8MJLTZYzI5slogneqsUcigOUl6JI89wMSW4QNNaMt1QNq0QncIinaZojwgtc2FlU0FnFQr/ZrV++e+1Em93gGLgv3KcI/ZaIibuy+VneOp68awstjdGeYvV/mbghzMzpgd60eXyqxfZZqxlfzD0xeV5h2VjPuddrODlFw==</diagram><diagram id="48a959eb-b0c7-ee78-ce0b-ed0e1b461dec" name="Environment">7Vpbb6M4FP41eY0AcwmPvaQ7K3WlSn3YmaeVCy54anBknCbZX7/HYC7GtJOZ0maVKQ+R+Xzl+845PoYs0FWx/0PgTf4XTwlbeE66X6DrhefF/gp+FXBogMD3GiATNG0gpwfu6b+kAd0W3dKUVBprIMk5k3RjggkvS5JIA8NC8J3Z7JGz1AA2OCMWcJ9gZqN/01TmDboKnB7/QmiWtzO7jq55wMlTJvi21PMtPPRYX011gduxdPsqxynfDSC0XqArwblsSsX+ijBFrUnbzQu13boFKeUxHfymwzNmW/3o90Q804QAqEpE6HXKQ8sNLHmjisU+U9ovE1olfFnVjavlI2WkKS/QZS4LBi1dKKa4yoma1IEbaMSuOOOiHhFF64twrfBKCv5EBjU39dXVtFoATZcwg6Sg2C1+IOyOV1RSXkLdA5eSF4MGF4xmqkLyDaB8KxktYY7WcNS8mgToQPYvEul28oDVE14QKQ7QRHdAUdB00RbfmfKut5/WfPKB6YS6G9YWm3Uj96pBQQs3LWJoaURSMGd9y4XMecZLzNY9elnbaCfIQKjvRMqD9ki8lVxx1o1wyxWJdTtSphfK0+C25CVpkBuqFjngVC3kdUZh3XwrEt1KsyGxyIgcmKjNuyAMS/psjv4WFgPLFeCJkrzA4unTGX7OGTzfOZkzRJaMlmim7e9yKsn9BtcmuAMVTa1G8uhoPiGPU1/zEOg7JoEo8CwCXTTBoOvMQKEbzBlQyJ7KrxpW5W+qvAz03R0RFBaoPKRpUcJiv/ZN1O23YZ3d4fU4dGw8+7V4tbLjVfzGeFV3hUfCh0GDDaelrAYj3ylgYDCuuf2gVTRSvBmx179b2lEmsfqxV3WpjDOOcANjML1GCzYOokWVYLJMGN+mdSiFdOQf8M+nOmkbO6TjRKvraCa3C0duF9pu5/u217Wx7C1OF39mYjNlYrEpou+gD9t82n1uSsWQwUSXDyBjmKnSn2UlcTlVYwkNZMgj/GgopoawpjwB8mpDGGtR0DSt4/fUNmjG9JQKEKrRFmKg4nIWp4u8kV7xMrAU8yYU82dwOxfNuteddDNy26PyjLvR0Ty6luV/ps8zpc+o9ZCPiGDhj3f6n8qfX86TJ8LVLOSFBnlh+0TDYNKm00bqHHsz0HfE8eMMEiWvTYxakj07Yr9XouT+HrkoCpzTUWwno2dJsWOGiqj13g+g2LMzxbOkOPZPR7GdkpwjxT5anSxQtIxOnlppd8BxXIv4/8eRZpZ8Izbpj2z6o4lkDc1BPzqOftvuz4f+GJkBJrQDzLvR/9rXswH99hHzbOhHKDqd9dtfbCbp98+Y/pV7Ouu3T4qT9NsfE86Gft8z37p/qPV/vjCeawsZxbAosFWc6XUL3Pb/7Wg+w/T/n0Hr/wA=</diagram></mxfile>

1
MEDIA/CETIC.xml Normal file
View File

@ -0,0 +1 @@
<mxfile userAgent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36" version="8.6.2" editor="www.draw.io" type="device"><diagram id="4ae0d6b8-8530-0065-81ea-747f68b336d0" name="Monolithic Kernel">5ZfbjpswEIafhstKgAmHy02yu63abatGVa8dmIAVg6kxIenT12BzWlLtSiXRKpuLxP5nfOCb8RAbaJUeHznOkycWATVsMzoaaG3YduC48rsWTkpwF5YSYk4iJZm9sCF/QIlWq5YkgkJrShKMUUHysRiyLINQjDTMOavGbjtGo5GQ4xgmwibEdKr+IpFIlOovzF7/CCRO2pUtU1u2ONzHnJWZXs+w0a75KHOK27m0f5HgiFUDCd0baMUZE6qVHldAa7RjbA//sHb75pCJ1wxAasAB01I/+s8CuGG7VA5fbnm9RXHSWNzfZb2v5Y5l4kPRBO1OOlhBLuO+7O2yFde/mxyHMNNcGlc33m4gQ/0YpjRXCRGg1kPrSuak1BKRUtmz9Co6y6yg7hNKV4wy3syFogX4kSP1QnC2h4HFt7fIdbv1h2A16wNwAceBpEE/AktB8JN0aU+Fjrk+E5ar+1WfYa1LMkyu1g/rpI67mfvAyoaO7fk4O5M43+U5JSEWhGU3wNbyX4bb+QzpzgF3MYH7hWw5bvb3g5WCZLKW3R7jroi9xLirjv8D2Z1A/gw8q18776tWBd7a9Lwr1yp0JtQXq1XeJNIPRJK0zc2pEJBe9ihdB+/zo3SO79mj5MzA15/wXcOB1NlvfpJjv90i39e+DubgG0z4fgVRMb4nWXyDbB3zimzbC8IA7nfOQihkVTCfcCb/mKf1o82G2XszmJ3LYZbd/srR2AbXOnT/Fw==</diagram><diagram id="1579a128-86fe-0ab2-80d5-6164026339a6" name="Unikernel">3ZZLj5swEMc/DcdKBhMIx91kd1upD6k59OzABKwYTI0JpJ++BpuX3GojNV2t4IDs/4wf85sZhIN3efsiSJl94Qkwx0NJ6+C943mRH6h3J1y1EGxcLaSCJlpCk3Cgv0CL7qDWNIHKaFqSnDNJy6UY86KAWC40IgRvlm4nzpKFUJIULOEQE2arP2giM61uN2jSPwJNs+FkFxnLkcTnVPC6MOc5Hj71jzbnZNjL+FcZSXgzk/CTg3eCc6lHebsD1qFdYnv+i3W8t4BC3rIA6wUXwmoT+kNZMhoTSXlhriivA5Y+MOiWIgc/NhmVcChJ3FkbVQdKy2TO1MxVwxMvpMmsG3VzytiOMy76vXAU7lEYKr2Sgp9hZtl6RxwEymIHY+K7gJDQziQT3AvwHKS4KpfBujWgTSG6gZk3U1pHn2yW0sGPmEpKx60nmmpggP4Zrm/B/UyPgvT3+85rSQtV4+tjPBb3a4zHrvkXyBu7ghMBlQIbMHXO41GoUdqNNMaZPMMe/Ky7luuBfqh6og/KwY3KdjIOG60gZ6H/elugwE4Z9u6QssBK2TNVKD10uFYS8jX2BL61J/w78A0tvnu40K720Se19tsa+d76Xb8H363F9yvIhoszLdIVsvXRG7KNLLb3Ixq+G6L+/yOqptPvY2+b/aLjp98=</diagram><diagram id="1f16b7f1-591d-5d02-d98e-e921793cd93b" name="network topology">7VnLcpswFP0abz08zMPLPOx0kXYy9aLtqiMLGdQAYoTwo1/fC5JsQKTNJHaSxvHClo4uEpyjI13hkXuVbW84KpLPLCLpyLGi7ci9HjnOdOLDdw3sJOB7tgRiTiMJWQdgQX8TCdoarWhESoVJSDCWClp0QczynGDRwRDnbNMNW7E06gAFiokBLDBKTfQbjUQi0dCzDvgnQuNEj2xbqmWJ8H3MWZWr8UaOu2o+sjlDui8VXyYoYpsW5M5G7hVnTMhStr0iaU1tl7b5A637++YkF4+6wFH3IXb62UkEVKgq4yJhMctROjugl83zkboHC2qJyFIo2lCEQfnue7vyow4ae7p6RzjNiCBcXfuLCLFT8qNKMIAOQ94yVqi+ViwXKswOms6ii1pmqOcsJxKZ0zTV/VZZoeJ9qJaCs/u9kkDypcmToq5kFceKCcWNQDwmKsqTUM1R6zLF7Q1h8HB8BwGcpEjQdXc6ITUr433cQRkoKHGGhVL3skZpRfTU6gkHc6moi9k2rk05xrTEbAxiAd+l+u3qFaEy2eu4AvquWMp405sbzC78mbUnr9Xi45AsV4O0rgkXFGx0i5YkvWMlFZTl0LZkQrCsFXCR0rhuELXEl3BrKc1hDO1ma0DzByWr+yTbv8qhWt1gIi9Ry5Kj65uDyYNQQknL3577fAGnxzTa2/aNa/omeC3fuE/1TUn4uvYN2ILI8jG8M28+/6N3vEnQ8Y49sQzveJ7pncB5voi2e5JdyhpP38dG5ZmG81/LcN7TDYcrTsUOHMfJBtUDPNZvqxATjIf8tgy9iWcd028nsJbjhWOvuzH5gWEuvYO0zaXDniOY/2/BWjL0mO+tZ0NrIGgcUSDnGmTFiuO8Ns+gKv25kROxYfy+HOOUVZHivy29zK6PokPYzw48LUtLhqk1kB9YR1jjbIP2d5sgBOZ65bzWehU8eb3aUIETUo7r+Vmf+YqfEjr3PKHnonDIRb5tusg9hossQ71366LwDaXZ4UeafZo0252+YJo9MVT8RpYALKQwfUXhkURXra4Qau63VVMQUtxiIKpRvE96RqOo8eYmoYIsCtRM+g1MHMOvJxDB16/n9FnH9w0RbGcgEXCOsYSZGfT1l8WHCs7EfkkVzLT4q3yDdjb8u/q1l16KBk78p+PfzMvm+lx4NgrsX3zoXMp9SQXMPX22BZYg9QFUncvORwt/2jWDdzopoHr4B6hpa/3L5s7+AA==</diagram><diagram name="deployment" id="ba9e9bd3-eff4-526b-ff8d-8600c9c1e103">7VrLluI2EP0aluNj+e1lPyBZzOT0CYtJVjnGFrbSxiKyaCBfn7Il+SV3D9NtmDMBFo11JZXkunVLj2ZmP2wOv7Bom32hCc5nlpkcZvbjzLJCx4O/FXAUgOciAaSMJAIyW2BJ/sUCRArdkQSXEhMQpzTnZNsHY1oUOOY9LGKM7vvN1jRPesA2SrEGLOMo19GvJOGZQAPXbPFfMUkzNTIyZc0qip9TRneFHG9m2ev6I6o3kbIl25dZlNB9B7LnM/uBUcrF0+bwgPPKtX23LV6pbebNcMFP6hCIHi9RvsNqyvXE+FE5AxfJXeVTKBW0APA+45scSggeS87oc+MkmP/9mhZcMor8qkzy/IHmlNXW7MTFQeI0PTs1gbWyPQ9qxAxwonHUvhVqfAUhiOkGc3aEJvuWLMVV1uFJYQznEScvffORjJm0MdeM8EQJDGyZMrwt3xZdZHQ7gdk3UdIdi7Hs1fX+NwwN7fCIpZhrduCh89YtVHP7Cs/hjefv5tlB1jQ8Dw2dj+cRVsG9S1mkjGc0pUWUz1v0vk5XuDJg9jkHFtjxj27hz6qR4ariE2YEJoeZ7Ps35vwoYyLacQpQO+RnSrfS1jB09MgDZEGqtxR2d5utbO+NxuKpkQSeqSkTkBSf8L6A/PF4OzmQetS9wZP9bTnC0rCtHjeHtFpjjZiUMTWALPB3Kb/7fCVRmTU8DuToz++8uTkmRy8O8Go96tYXzDiBVfFztML5Ey0JJ7SAuhXlnG46De5yklYVvKL4HqaWkwLGUIuzOcK5dAAYwIfvlb/sYPtOT1aWKnfSgx+MpAf74wQ6UwrtJ9ONq+sGmeNMTS4c973CKTF7qYQDusDieQrxLOrPzyge1/F74kGOqYnHdXXx+NbHSfTOskqZRvg/Xah8XXDBhfTmv19v8Y4RfgTBMbyPqgFOlds6iHEcj8ltFbiOa04ptzMoy3IDw+0vTJ6vacsKdW2pZh8h7IQDXYeGgecH6WwsBQLHCQFPPAKtsfRxUYlnlJVhbBSY7yl7Lo04p7tE+r9LvTgsT8JDMNwduIqWDg3hG8eHj9AQXvH+QN3idPOVfaF8pcZ+R8LaEx5nuDSqAK3ucLZ/Ceja9wkDGQVjMvKQLiN7AhkhpLF3RTqyfuBGWw1+22lPvdO2w8vttJF+0fAVrwBYCmKGjMJb8rGLP0WEDP8uaxKKpG9j8ErN+NDpG5IktTz3GeF4uY3qMN9D4GiSPQMJnrpxV8cdz9NIQNbIZsCaIos5GguPvy1vLFgOuiQL+t3B7+IW7Wr8b7v9fzjYI4f+8/nf0/y/UGfDq2GgychqO2VfkgH9ND8/gJdg9wOoPJtdDxde2BeDe0EqrLFzipdz+aY9Brx/dlRVfCprH9xBA+RtD20lPKXVN24IFdZWTNWg0DKQFxjINA0YfVHdYYs2UBCDioZ61+uJiWB4d+Prhx3kj5x2prg0UNOdPCiaO7g3ggKJoAhvQTFyo+f8yKgYO4lNERWkeDVVQIYwblni1YBwBvvYM4YDFNufA4lfBLQ/ubLn/wE=</diagram></mxfile>

BIN
MEDIA/PoC Topology.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
MEDIA/unikernel_network.PNG Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

@ -0,0 +1,5 @@
FROM alpine:latest
RUN mkdir /service
COPY runnableService /service
WORKDIR /service
CMD sleep 1 && ./runnableService "$(hostname -i)"

View File

@ -0,0 +1,3 @@
#!/bin/bash
docker run --rm -it -v "${PWD}":/usr/src/build -w /usr/src/build cetic/compiler g++ -std=c++11 -static -o runnableService *.cpp

View File

@ -0,0 +1,3 @@
#!/bin/bash
docker build -t cetic/dns .

View File

@ -0,0 +1,283 @@
/**
* Basic DNS server for the IncludeOS unikernel framework.
*
* This code uses portions of code created by GitHub user tomasorti for his dns-server project (https://github.com/tomasorti/dns-server)
*/
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <map>
#include <vector>
#define SERVER_PORT 53
#define BUFFER_SIZE 1024
static const unsigned int QR_MASK = 0x8000;
static const unsigned int OPCODE_MASK = 0x7800;
static const unsigned int AA_MASK = 0x0400;
static const unsigned int TC_MASK = 0x0200;
static const unsigned int RD_MASK = 0x0100;
static const unsigned int RA_MASK = 0x8000;
static const unsigned int RCODE_MASK = 0x000F;
static const unsigned int HDR_OFFSET = 12;
// for more info on DNS fields, see RFC 1035
struct queryHeader {
unsigned int id; // 16 bit identifier assigned by the program who generated the query
unsigned int query; // identifies if message is query (0) or a response (1)
unsigned int opcode; // 4 bit field specifying kind of query: standard (0), inverse (1), server status request (2), reserved (3-15)
unsigned int aa; // bit indicating if responding server is an authority for the domain name
unsigned int truncation; // specifies whether this message was truncated or not
unsigned int recursionDesired; // may be set in a query, directs the name server to pursue the query recursively
unsigned int recursionAvailable; // set in a response, indicates whether recursive queries are available
unsigned int responseCode; // 4 bit response code: 0 - no error, 1 - format error, 2 - server failure, 3 - name error, 4 - not implemented, 5 - refused
// unsigned 16-bit integers
unsigned int questionCount; // number of entries in the question section
unsigned int answerCount; // number of resource reconds in the answer section
unsigned int nameServerCount; // number of name server resource records in the authority records section
unsigned int additionalResourceCount; // number of resource records in the additional records section
};
struct queryQuestion {
std::string queryName; // domain name requested
unsigned int queryType; // 2 octet code specifying the type of the query
unsigned int queryClass; // 2 octet code specifying the class of the query
};
queryHeader pQueryHeader;
queryQuestion pQueryQuestion;
std::map<std::string,std::vector<int>> resourceRecords;
unsigned int get16bits(char*& buffer) {
unsigned int value = static_cast<unsigned char> (buffer[0]);
value = value << 8;
value += static_cast<unsigned char> (buffer[1]);
buffer += 2;
return value;
}
void put8bits(char*& buffer, unsigned int value) throw () {
buffer[0] = (value);
buffer += 1;
}
void put16bits(char*& buffer, unsigned int value) throw () {
buffer[0] = (value & 0xFF00) >> 8;
buffer[1] = value & 0xFF;
buffer += 2;
}
void put32bits(char*& buffer, unsigned long value) throw () {
buffer[0] = (value & 0xFF000000) >> 24;
buffer[1] = (value & 0xFF0000) >> 16;
buffer[2] = (value & 0xFF00) >> 16;
buffer[3] = (value & 0xFF) >> 16;
buffer += 4;
}
queryHeader decodeHeader(char* data, queryHeader pQueryHeader){
pQueryHeader.id = get16bits(data);
unsigned int fields = get16bits(data);
pQueryHeader.query = fields & QR_MASK;
pQueryHeader.opcode = fields & OPCODE_MASK;
pQueryHeader.aa = fields & AA_MASK;
pQueryHeader.truncation = fields & TC_MASK;
pQueryHeader.recursionDesired = fields & RD_MASK;
pQueryHeader.recursionAvailable = fields & RA_MASK;
pQueryHeader.questionCount = get16bits(data);
pQueryHeader.answerCount = get16bits(data);
pQueryHeader.nameServerCount = get16bits(data);
pQueryHeader.additionalResourceCount = get16bits(data);
return pQueryHeader;
}
queryQuestion decodeQuery(char*& data, queryQuestion pQueryQuestion){
pQueryQuestion.queryName = "";
int length = *data++;
while (length != 0) {
for (int i = 0; i < length; i++) {
char c = *data++;
pQueryQuestion.queryName.append(1, c);
}
length = *data++;
if (length != 0) pQueryQuestion.queryName.append(1,'.');
}
pQueryQuestion.queryType = get16bits(data);
pQueryQuestion.queryClass = get16bits(data);
return pQueryQuestion;
}
void codeDomain(char*& buffer, const std::string& domain) {
int start = 0, end; // indexes
while ((end = domain.find('.', start)) != std::string::npos) {
*buffer++ = end - start; // label length octet
for (int i=start; i<end; i++) {
*buffer++ = domain[i]; // label octets
}
start = end + 1; // Skip '.'
}
*buffer++ = domain.size() - start; // last label length octet
for (int i=start; i<domain.size(); i++) {
*buffer++ = domain[i]; // last label octets
}
*buffer++ = 0;
}
int processQuery(char* buffer, queryHeader pQueryHeader, queryQuestion pQueryQuestion){
// search for domain in resourceRecords
bool bRRexists = true;
std::map<std::string,std::vector<int>>::iterator record = resourceRecords.find(pQueryQuestion.queryName);
if (record == resourceRecords.end())
bRRexists = false;
char* bufferBegin = buffer;
// create header
put16bits(buffer, pQueryHeader.id);
int fields = (1 << 15); // Response code
fields += (0 << 11); // Opcode
fields += (0 << 10); // Authoritative code
fields += (0 << 9); // Truncated code
fields += (1 << 8); // Recursion desired code
fields += (0 << 7); // Recursion available code
fields += (0 << 6); // Z reserved code
fields += (0 << 5); // Answers authenticated code
fields += (0 << 4); // Non-authenticated data code
if(bRRexists && pQueryQuestion.queryType == 1)
fields += 0; // Reply code
else
fields += 3;
put16bits(buffer, fields);
put16bits(buffer, pQueryHeader.questionCount); // Questions count
if(bRRexists && pQueryQuestion.queryType == 1)
put16bits(buffer, 1); // Answers count
else
put16bits(buffer, 0);
put16bits(buffer, 0); // Authority RRs
put16bits(buffer, 0); // Additional RRs
// create domain query section - copy original question format
codeDomain(buffer, pQueryQuestion.queryName);
put16bits(buffer, pQueryQuestion.queryType);
put16bits(buffer, pQueryQuestion.queryClass);
// if requested domain exists in resourceRecords, create the answer
if(bRRexists && pQueryQuestion.queryType == 1){
// compression code to pointing to original question - should be offset from ID to domain name (in number of 16bits)
put16bits(buffer, 49164);
put16bits(buffer, pQueryQuestion.queryType);
put16bits(buffer, pQueryQuestion.queryClass);
put32bits(buffer, 0); // time to live
put16bits(buffer, 4); // data length (always 4 for IPv4 addresses)
put8bits(buffer,resourceRecords[pQueryQuestion.queryName][0]);
put8bits(buffer,resourceRecords[pQueryQuestion.queryName][1]);
put8bits(buffer,resourceRecords[pQueryQuestion.queryName][2]);
put8bits(buffer,resourceRecords[pQueryQuestion.queryName][3]);
}
int size = buffer - bufferBegin;
return size;
}
int main(int argc, char *argv[])
{
resourceRecords["www.cetic.be"].push_back(10);
resourceRecords["www.cetic.be"].push_back(0);
resourceRecords["www.cetic.be"].push_back(0);
resourceRecords["www.cetic.be"].push_back(5);
resourceRecords["cetic.be"].push_back(10);
resourceRecords["cetic.be"].push_back(0);
resourceRecords["cetic.be"].push_back(0);
resourceRecords["cetic.be"].push_back(5);
resourceRecords["internship.cetic.be"].push_back(10);
resourceRecords["internship.cetic.be"].push_back(0);
resourceRecords["internship.cetic.be"].push_back(0);
resourceRecords["internship.cetic.be"].push_back(5);
// define address and socket variables
struct sockaddr_in serverAddress;
int serverSocket;
struct sockaddr_in clienAddress;
socklen_t clientAddressLength = sizeof(clienAddress);
int bytesReceivedLength;
char receiveBuffer[BUFFER_SIZE];
// creating UDP socket
if ((serverSocket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("cannot create socket");
return 0;
}
// defining server address properties
memset((void *)&serverAddress, 0, sizeof(serverAddress));
serverAddress.sin_family = AF_INET;
serverAddress.sin_addr.s_addr = inet_addr(argv[1]);
//serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);
serverAddress.sin_port = htons(SERVER_PORT);
// binding to UDP socket
if (bind(serverSocket, (struct sockaddr *)&serverAddress, sizeof(serverAddress)) < 0) {
perror("bind failed");
return 0;
}
printf("Service IP address is %s on port %d\n", inet_ntoa(serverAddress.sin_addr), ntohs(serverAddress.sin_port));
for (;;) {
bytesReceivedLength = recvfrom(serverSocket, receiveBuffer, BUFFER_SIZE, 0, (struct sockaddr *)&clienAddress, &clientAddressLength);
printf("received %d bytes\n", bytesReceivedLength);
if (bytesReceivedLength > 0) {
char* data = &receiveBuffer[0];
pQueryHeader = decodeHeader(data, pQueryHeader);
data += HDR_OFFSET;
pQueryQuestion = decodeQuery(data, pQueryQuestion);
// debug output
printf("####### INCOMMING REQUEST #######\n");
printf("Getting UDP data from %s:%d\n", inet_ntoa(clienAddress.sin_addr), ntohs(clienAddress.sin_port));
printf("Header:\n");
printf("\tID: %u\n",pQueryHeader.id);
printf("\tQuery: %u\n", pQueryHeader.query);
printf("\topCode: %u\n", pQueryHeader.opcode);
printf("\tAA: %u\n", pQueryHeader.aa);
printf("\tTruncation: %u\n", pQueryHeader.truncation);
printf("\tRecursion Desired: %u\n", pQueryHeader.recursionDesired);
printf("\tRecursion Available: %u\n", pQueryHeader.recursionAvailable);
printf("\tReponse Code: %u\n", pQueryHeader.responseCode);
printf("\tQuestion Count: %u\n", pQueryHeader.questionCount);
printf("\tAnswer Count: %u\n", pQueryHeader.answerCount);
printf("\tName Server Count: %u\n", pQueryHeader.nameServerCount);
printf("\tAdditional Resource Count: %u\n", pQueryHeader.additionalResourceCount);
printf("Query:\n");
printf("\tQuery name: %s\n", pQueryQuestion.queryName.data());
printf("\tQuery Type: %u\n", pQueryQuestion.queryType);
printf("\tAdditional Resource Count: %u\n", pQueryQuestion.queryClass);
printf("#################################\n");
// send reply
char buffer[BUFFER_SIZE];
int nbrBytes = processQuery(buffer, pQueryHeader, pQueryQuestion);
sendto(serverSocket, buffer, nbrBytes, 0, (struct sockaddr *)&clienAddress, clientAddressLength);
}
}
}

View File

@ -0,0 +1,3 @@
#!/bin/bash
docker run --rm -d cetic/dns

View File

@ -0,0 +1,10 @@
#!/bin/bash
# Building binary from C++ code (statically linking libraries)
docker run --rm -it -v "${PWD}":/usr/src/build -w /usr/src/build cetic/compiler g++ -std=c++11 -static -o runnableService *.cpp
# Building the container (expecting the Dockerfile to be present)
docker build -t cetic/dns .
# Launching the service in a Docker container
docker run --rm -d cetic/dns

View File

@ -0,0 +1,2 @@
FROM alpine:latest
RUN apk add --no-cache gcc g++

View File

@ -0,0 +1,45 @@
# Container Code
This folder contains the container version of the unikernel services.
Each folder holds:
* The CPP file containing the code
* A **compile.sh** script to compile the CPP file into a runnable service
* A **Dockerfile** to create the container for this service
* A **create_container.sh** script to create to container from the Dockerfile
* A **run_service.sh** script to run the created container in detached mode
* A **start.sh** script that will compile the binary from code, build the Docker container and run it (in detached mode)
The following section briefly explains the steps taken.
## Pre Requisite
Before running the **compile.sh** or **start.sh** scripts, you must first build the **builder** container from the Dockerfile in this parent folder.
This can be done by running the **create_compiler.sh** script or running the following command from the CONTAINER directory:
```
docker build -t cetic/compiler .
```
## Compiling the binary (*compile.sh*)
*Requires the cetic/compiler container image*
This script will launch a new cetic/compiler image container, mapping the current folder to a folder inside the container, then it will staticaly compile the C++ code in the .cpp file in the directory and output a *runnableService* binary.
## Creating the container
This will create the service container using the **Dockerfile**.
It will use the lastest version of alpine base image and copy the **runnableService** executable inside the container.
## Running the container
When running the container, it will execute the command instructed in the **Dockerfile**.
The container will wait for the network to be up (sleep 1) then it will launch the service binary, passing the container's IP address to bind the service to as a paramater.
The script starts it in detached mode (i.e.: in the background)
**NB:** as of now, the IP address is not given statically, you must run `docker network inspect bridge` to view the IP address assigned to the container.

View File

@ -0,0 +1,6 @@
FROM alpine:latest
RUN mkdir /service
COPY runnableService /service
COPY index.html /service
WORKDIR /service
CMD sleep 1 && ./runnableService "$(hostname -i)"

View File

@ -0,0 +1,3 @@
#!/bin/bash
docker run --rm -it -v "${PWD}":/usr/src/build -w /usr/src/build cetic/compiler g++ -std=c++11 -static -o runnableService *.cpp

View File

@ -0,0 +1,3 @@
#!/bin/bash
docker build -t cetic/webserver .

View File

@ -0,0 +1,15 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>CETIC Internship Unikernel Web Page</title>
<link href="https://fonts.googleapis.com/css?family=Ubuntu:500,300" rel="stylesheet" type="text/css">
</head>
<body>
<h1 style="font-family: Arial, sans-serif">
CETIC Internship Unikernel Web Page
</h1>
<hr />
<p>This is the first web server spawn from a unikernel during the CETIC Intership 2017-18</p>
</body>
</html>

View File

@ -0,0 +1,3 @@
#!/bin/bash
docker run --rm -d cetic/webserver

View File

@ -0,0 +1,10 @@
#!/bin/bash
# Building binary from C++ code (statically linking libraries)
docker run --rm -it -v "${PWD}":/usr/src/build -w /usr/src/build cetic/compiler g++ -std=c++11 -static -o runnableService *.cpp
# Building the container (expecting the Dockerfile to be present)
docker build -t cetic/webserver .
# Launching the service in a Docker container
docker run --rm -d cetic/webserver

View File

@ -0,0 +1,120 @@
/*
* This code is adapted from the IncludeOS Acorn web server example.
*/
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string>
#include <cstring>
#include <fstream>
#define SERVER_PORT 80
#define BUFFER_SIZE 2048
bool isIndexRequested(char receiveBuffer[]) {
// if only / is requested
if(receiveBuffer[4] == '/' && receiveBuffer[5] == ' ')
return true;
// if only /index.html is requested
char request[25];
memcpy(request, receiveBuffer, 24);
request[25] = '\0';
char *output = NULL;
output = strstr(request," /index.html ");
if(output)
return true;
return false;
}
int main(int argc, char *argv[])
{
// define address and socket variables
struct sockaddr_in serverAddress;
int serverSocket;
int clientSocket;
struct sockaddr_in clientAddress;
socklen_t clientAddressLength = sizeof(clientAddress);
int bytesReceivedLength;
char receiveBuffer[BUFFER_SIZE];
// Retrieve the HTML page from the disk
std::ifstream file("index.html", std::ios::binary | std::ios::ate);
std::streamsize indexLength = file.tellg();
file.seekg(0, std::ios::beg);
char indexArray[indexLength];
file.read(indexArray, indexLength);
// creating error message
std::string error = "HTTP/1.1 404 Not Found\r\nContent-Type: text/html\r\n\r\n<html><body>Page not found</body></html>\r\n";
int errorLength = error.length();
// declaring character array
char errorArray[errorLength+1];
strcpy(errorArray, error.c_str());
// creating TCP socket
if ((serverSocket = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("cannot create socket");
return 0;
}
// defining server address properties
memset((void *)&serverAddress, 0, sizeof(serverAddress));
serverAddress.sin_family = AF_INET;
serverAddress.sin_addr.s_addr = inet_addr(argv[1]);
//serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);
serverAddress.sin_port = htons(SERVER_PORT);
// binding to UDP socket
if (bind(serverSocket, (struct sockaddr *)&serverAddress, sizeof(serverAddress)) < 0) {
perror("bind failed");
return 0;
}
// set the socket for listening (queue backlog of 5)
if (listen(serverSocket, 5) < 0) {
perror("listen failed");
return 0;
}
printf("Service IP address is %s on port %d\n", inet_ntoa(serverAddress.sin_addr), ntohs(serverAddress.sin_port));
for (;;) {
clientSocket = accept(serverSocket, (struct sockaddr *)&clientAddress, &clientAddressLength);
bytesReceivedLength = read(clientSocket, receiveBuffer, BUFFER_SIZE);
printf("####### INCOMMING REQUEST #######\n");
printf("Received a connection from: %s port %d\n", inet_ntoa(clientAddress.sin_addr), ntohs(clientAddress.sin_port));
printf("received %d bytes\n", bytesReceivedLength);
if (bytesReceivedLength > 0) {
// TODO respond only to GET and / or /index.html
if(receiveBuffer[0] == 'G' && isIndexRequested(receiveBuffer) ) { //request is not a GET
// debug output
printf("%s", receiveBuffer);
// send reply
//printf("%s", indexArray);
int nbytes = write(clientSocket, indexArray, indexLength);
printf("%d sent to client\n", nbytes);
} else {
printf("%s", receiveBuffer);
int nbytes = write(clientSocket, errorArray, (errorLength+1));
printf("%d bytes sent to client\n", nbytes);
}
printf("#################################\n");
shutdown(clientSocket, 2);
}
}
}

View File

@ -0,0 +1,3 @@
#!/bin/bash
docker build -t cetic/compiler .

21
SOURCE/README.md Normal file
View File

@ -0,0 +1,21 @@
# Source Code
This folder contains the source code of the unikernel projects created with the [IncludeOS framework](https://github.com/hioa-cs/IncludeOS)
Each folder contains the source code for a single unikernel.
## Building Unikernel Image
**Requires IncludeOS to be installed on the system**
The script **cmake_build.sh** can be executed to build the each unikernel images. The .img disk file will be located in the **build** folder inside the project folder.
## Container Versions
The **CONTAINER** folder contains the container versions of the unikernel images.
The container versions are aimed to be analogs of the unikernel code but adapted to run in a standalone Docker container.
## Deployment
For deploying the unikernel or container environment, see the [DEPLOYMENT](https://git.cetic.be/stages/unikernels/tree/feature/stagelongree2018/DEPLOYMENT) folder for deployment scripts.

View File

@ -0,0 +1,36 @@
cmake_minimum_required(VERSION 2.8.9)
# IncludeOS install location
if (NOT DEFINED ENV{INCLUDEOS_PREFIX})
set(ENV{INCLUDEOS_PREFIX} /usr/local)
endif()
include($ENV{INCLUDEOS_PREFIX}/includeos/pre.service.cmake)
project (DNS)
# Human-readable name of your service
set(SERVICE_NAME "CETIC DNS Service")
# Name of your service binary
set(BINARY "DNS")
# Source files to be linked with OS library parts to form bootable image
set(SOURCES
service.cpp # ...add more here
)
# To add your own include paths:
# set(LOCAL_INCLUDES ".")
# DRIVERS / PLUGINS:
set(DRIVERS
virtionet # Virtio networking
# virtioblock # Virtio block device
# ... Others from src/drivers
)
set(PLUGINS
)
# include service build script
include($ENV{INCLUDEOS_PREFIX}/includeos/post.service.cmake)

View File

@ -0,0 +1,7 @@
#!/bin/bash
mkdir -p build
pushd build
cmake ..
make
popd

View File

@ -0,0 +1,11 @@
{
"net": [
{
"iface": 0,
"config": "static",
"address": "10.0.0.100",
"netmask": "255.255.255.0",
"gateway": "10.0.0.254"
}
]
}

View File

@ -0,0 +1,262 @@
/**
* Basic DNS server for the IncludeOS unikernel framework.
*
* This code uses portions of code created by GitHub user tomasorti for his dns-server project (https://github.com/tomasorti/dns-server)
*/
#include <service>
#include <net/inet4>
#include <map>
#include <vector>
using namespace net;
#define SERVER_PORT 53
static const uint QR_MASK = 0x8000;
static const uint OPCODE_MASK = 0x7800;
static const uint AA_MASK = 0x0400;
static const uint TC_MASK = 0x0200;
static const uint RD_MASK = 0x0100;
static const uint RA_MASK = 0x8000;
static const uint RCODE_MASK = 0x000F;
static const uint HDR_OFFSET = 12;
static const int BUFFER_SIZE = 1024;
// for more info on DNS fields, see RFC 1035
struct queryHeader {
uint id; // 16 bit identifier assigned by the program who generated the query
uint query; // identifies if message is query (0) or a response (1)
uint opcode; // 4 bit field specifying kind of query: standard (0), inverse (1), server status request (2), reserved (3-15)
uint aa; // bit indicating if responding server is an authority for the domain name
uint truncation; // specifies whether this message was truncated or not
uint recursionDesired; // may be set in a query, directs the name server to pursue the query recursively
uint recursionAvailable; // set in a response, indicates whether recursive queries are available
uint responseCode; // 4 bit response code: 0 - no error, 1 - format error, 2 - server failure, 3 - name error, 4 - not implemented, 5 - refused
// unsigned 16-bit integers
uint questionCount; // number of entries in the question section
uint answerCount; // number of resource reconds in the answer section
uint nameServerCount; // number of name server resource records in the authority records section
uint additionalResourceCount; // number of resource records in the additional records section
};
struct queryQuestion {
std::string queryName; // domain name requested
uint queryType; // 2 octet code specifying the type of the query
uint queryClass; // 2 octet code specifying the class of the query
};
queryHeader pQueryHeader;
queryQuestion pQueryQuestion;
std::map<std::string,std::vector<int>> resourceRecords;
uint get16bits(const char*& buffer) {
uint value = static_cast<u_char> (buffer[0]);
value = value << 8;
value += static_cast<u_char> (buffer[1]);
buffer += 2;
return value;
}
void put8bits(char*& buffer, uint value) throw () {
buffer[0] = (value);
buffer += 1;
}
void put16bits(char*& buffer, uint value) throw () {
buffer[0] = (value & 0xFF00) >> 8;
buffer[1] = value & 0xFF;
buffer += 2;
}
void put32bits(char*& buffer, ulong value) throw () {
buffer[0] = (value & 0xFF000000) >> 24;
buffer[1] = (value & 0xFF0000) >> 16;
buffer[2] = (value & 0xFF00) >> 16;
buffer[3] = (value & 0xFF) >> 16;
buffer += 4;
}
queryHeader decodeHeader(const char* data, queryHeader pQueryHeader){
pQueryHeader.id = get16bits(data);
uint fields = get16bits(data);
pQueryHeader.query = fields & QR_MASK;
pQueryHeader.opcode = fields & OPCODE_MASK;
pQueryHeader.aa = fields & AA_MASK;
pQueryHeader.truncation = fields & TC_MASK;
pQueryHeader.recursionDesired = fields & RD_MASK;
pQueryHeader.recursionAvailable = fields & RA_MASK;
pQueryHeader.questionCount = get16bits(data);
pQueryHeader.answerCount = get16bits(data);
pQueryHeader.nameServerCount = get16bits(data);
pQueryHeader.additionalResourceCount = get16bits(data);
return pQueryHeader;
}
queryQuestion decodeQuery(const char*& data, queryQuestion pQueryQuestion){
pQueryQuestion.queryName = "";
int length = *data++;
while (length != 0) {
for (int i = 0; i < length; i++) {
char c = *data++;
pQueryQuestion.queryName.append(1, c);
}
length = *data++;
if (length != 0) pQueryQuestion.queryName.append(1,'.');
}
pQueryQuestion.queryType = get16bits(data);
pQueryQuestion.queryClass = get16bits(data);
return pQueryQuestion;
}
void codeDomain(char*& buffer, const std::string& domain) {
int start = 0, end; // indexes
while ((end = domain.find('.', start)) != std::string::npos) {
*buffer++ = end - start; // label length octet
for (int i=start; i<end; i++) {
*buffer++ = domain[i]; // label octets
}
start = end + 1; // Skip '.'
}
*buffer++ = domain.size() - start; // last label length octet
for (int i=start; i<domain.size(); i++) {
*buffer++ = domain[i]; // last label octets
}
*buffer++ = 0;
}
int processQuery(char* buffer, queryHeader pQueryHeader, queryQuestion pQueryQuestion){
// search for domain in resourceRecords
bool bRRexists = true;
std::map<std::string,std::vector<int>>::iterator record = resourceRecords.find(pQueryQuestion.queryName);
if (record == resourceRecords.end())
bRRexists = false;
char* bufferBegin = buffer;
// create header
put16bits(buffer, pQueryHeader.id);
int fields = (1 << 15); // Response code
fields += (0 << 11); // Opcode
fields += (0 << 10); // Authoritative code
fields += (0 << 9); // Truncated code
fields += (1 << 8); // Recursion desired code
fields += (0 << 7); // Recursion available code
fields += (0 << 6); // Z reserved code
fields += (0 << 5); // Answers authenticated code
fields += (0 << 4); // Non-authenticated data code
if(bRRexists)
fields += 0; // Reply code
else
fields += 3;
put16bits(buffer, fields);
put16bits(buffer, pQueryHeader.questionCount); // Questions count
if(bRRexists)
put16bits(buffer, 1); // Answers count
else
put16bits(buffer, 0);
put16bits(buffer, 0); // Authority RRs
put16bits(buffer, 0); // Additional RRs
// create domain query section - copy original question format
codeDomain(buffer, pQueryQuestion.queryName);
put16bits(buffer, pQueryQuestion.queryType);
put16bits(buffer, pQueryQuestion.queryClass);
// if requested domain exists in resourceRecords, create the answer
if(bRRexists){
// compression code to pointing to original question - should be offset from ID to domain name (in number of 16bits)
put16bits(buffer, 49164);
put16bits(buffer, pQueryQuestion.queryType);
put16bits(buffer, pQueryQuestion.queryClass);
put32bits(buffer, 0); // time to live
put16bits(buffer, 4); // data length (always 4 for IPv4 addresses)
put8bits(buffer,resourceRecords[pQueryQuestion.queryName][0]);
put8bits(buffer,resourceRecords[pQueryQuestion.queryName][1]);
put8bits(buffer,resourceRecords[pQueryQuestion.queryName][2]);
put8bits(buffer,resourceRecords[pQueryQuestion.queryName][3]);
}
int size = buffer - bufferBegin;
return size;
}
void Service::start()
{
resourceRecords["www.cetic.be"].push_back(10);
resourceRecords["www.cetic.be"].push_back(0);
resourceRecords["www.cetic.be"].push_back(0);
resourceRecords["www.cetic.be"].push_back(5);
resourceRecords["cetic.be"].push_back(10);
resourceRecords["cetic.be"].push_back(0);
resourceRecords["cetic.be"].push_back(0);
resourceRecords["cetic.be"].push_back(5);
resourceRecords["internship.cetic.be"].push_back(10);
resourceRecords["internship.cetic.be"].push_back(0);
resourceRecords["internship.cetic.be"].push_back(0);
resourceRecords["internship.cetic.be"].push_back(5);
// get the first network interfaces of the unikernel
auto& inet = Inet4::stack<0>();
Expects(inet.is_configured());
printf("Service IP address is %s\n", inet.ip_addr().str().c_str());
const UDP::port_t port = SERVER_PORT;
auto& sock = inet.udp().bind(port);
sock.on_read(
[&sock] (UDP::addr_t addr, UDP::port_t port, const char* data, size_t len){
pQueryHeader = decodeHeader(data, pQueryHeader);
data += HDR_OFFSET;
pQueryQuestion = decodeQuery(data, pQueryQuestion);
// debug output
printf("####### INCOMMING REQUEST #######\n");
printf("Getting UDP data from %s:%d\n", addr.str().c_str(), port);
printf("Header:\n");
printf("\tID: %u\n",pQueryHeader.id);
printf("\tQuery: %u\n", pQueryHeader.query);
printf("\topCode: %u\n", pQueryHeader.opcode);
printf("\tAA: %u\n", pQueryHeader.aa);
printf("\tTruncation: %u\n", pQueryHeader.truncation);
printf("\tRecursion Desired: %u\n", pQueryHeader.recursionDesired);
printf("\tRecursion Available: %u\n", pQueryHeader.recursionAvailable);
printf("\tReponse Code: %u\n", pQueryHeader.responseCode);
printf("\tQuestion Count: %u\n", pQueryHeader.questionCount);
printf("\tAnswer Count: %u\n", pQueryHeader.answerCount);
printf("\tName Server Count: %u\n", pQueryHeader.nameServerCount);
printf("\tAdditional Resource Count: %u\n", pQueryHeader.additionalResourceCount);
printf("Query:\n");
printf("\tQuery name: %s\n", pQueryQuestion.queryName.data());
printf("\tQuery Type: %u\n", pQueryQuestion.queryType);
printf("\tAdditional Resource Count: %u\n", pQueryQuestion.queryClass);
printf("#################################\n");
// send reply
char buffer[BUFFER_SIZE];
int nbrBytes = processQuery(buffer, pQueryHeader, pQueryQuestion);
sock.sendto(addr, port, buffer, nbrBytes);
});
INFO("DNS Server", "Listening on port %d\n", port);
}

View File

@ -0,0 +1,6 @@
{
"net" : [
{"device" : "virtio", "mac" : "c0:01:0a:00:00:2a"},
{"device" : "virtio", "mac" : "c0:01:0a:00:00:3a"}
]
}

View File

@ -0,0 +1,42 @@
cmake_minimum_required(VERSION 2.8.9)
# IncludeOS install location
if (NOT DEFINED ENV{INCLUDEOS_PREFIX})
set(ENV{INCLUDEOS_PREFIX} /usr/local)
endif()
include($ENV{INCLUDEOS_PREFIX}/includeos/pre.service.cmake)
project (Firewall)
# Human-readable name of your service
set(SERVICE_NAME "CETIC Firewall Service")
# Name of your service binary
set(BINARY "Firewall")
# Source files to be linked with OS library parts to form bootable image
set(SOURCES
service.cpp # ...add more here
)
# To add your own include paths:
# set(LOCAL_INCLUDES ".")
# DRIVERS / PLUGINS:
if ("$ENV{PLATFORM}" STREQUAL "x86_solo5")
set(DRIVERS
solo5net
)
else()
set(DRIVERS
virtionet # Virtio networking
# virtioblock # Virtio block device
# ... Others from src/drivers
)
endif()
set(PLUGINS
)
# include service build script
include($ENV{INCLUDEOS_PREFIX}/includeos/post.service.cmake)

View File

@ -0,0 +1,7 @@
#!/bin/bash
mkdir -p build
pushd build
cmake ..
make
popd

View File

@ -0,0 +1,41 @@
Iface outside {
address: 192.168.100.254,
netmask: 255.255.255.0,
index: 0
}
Iface inside {
address: 192.168.101.3,
netmask: 255.255.255.248,
gateway: 192.168.101.2,
index: 1
}
Gateway routing {
forward: firewallChain,
outside_route: {
net: 192.168.100.0,
netmask: 255.255.255.0,
iface: outside
},
firewall_to_router_route: {
net: 192.168.101.0,
netmask: 255.255.255.248,
iface: inside
},
inside_route: {
net: 10.0.0.0,
netmask: 255.255.255.0,
iface: inside
}
}
Filter::IP firewallChain {
Filter::ICMP {
if (icmp.type == echo-request) {
log("Dropped ping from ", ip.saddr, " to ", ip.daddr, "\n")
drop
}
}
accept
}

View File

@ -0,0 +1,6 @@
#include <os>
void Service::start()
{
printf("IncludeOS firewall booted up");
}

View File

@ -0,0 +1,6 @@
{
"net" : [
{"device" : "virtio", "mac" : "c0:01:0a:00:00:2a"},
{"device" : "virtio", "mac" : "c0:01:0a:00:00:3a"}
]
}

View File

@ -0,0 +1,42 @@
cmake_minimum_required(VERSION 2.8.9)
# IncludeOS install location
if (NOT DEFINED ENV{INCLUDEOS_PREFIX})
set(ENV{INCLUDEOS_PREFIX} /usr/local)
endif()
include($ENV{INCLUDEOS_PREFIX}/includeos/pre.service.cmake)
project (Router)
# Human-readable name of your service
set(SERVICE_NAME "CETIC Router Service")
# Name of your service binary
set(BINARY "Router")
# Source files to be linked with OS library parts to form bootable image
set(SOURCES
service.cpp # ...add more here
)
# To add your own include paths:
# set(LOCAL_INCLUDES ".")
# DRIVERS / PLUGINS:
if ("$ENV{PLATFORM}" STREQUAL "x86_solo5")
set(DRIVERS
solo5net
)
else()
set(DRIVERS
virtionet # Virtio networking
# virtioblock # Virtio block device
# ... Others from src/drivers
)
endif()
set(PLUGINS
)
# include service build script
include($ENV{INCLUDEOS_PREFIX}/includeos/post.service.cmake)

View File

@ -0,0 +1,7 @@
#!/bin/bash
mkdir -p build
pushd build
cmake ..
make
popd

View File

@ -0,0 +1,38 @@
{
"net" : [
{
"iface": 0,
"config": "static",
"address": "10.0.0.254",
"netmask": "255.255.255.0",
"gateway": "10.0.0.254"
},
{
"iface": 1,
"config": "static",
"address": "192.168.101.2",
"netmask": "255.255.255.248",
"gateway": "192.168.101.3"
}
],
"router" : [
[
{
"address": "10.0.0.0",
"netmask": "255.255.255.0",
"iface" : 0
},
{
"address": "192.168.101.0",
"netmask": "255.255.255.248",
"iface" : 1
},
{
"address": "0.0.0.0",
"netmask": "0.0.0.0",
"iface" : 1
}
]
]
}

View File

@ -0,0 +1,17 @@
/*
* This code is copied from the IncludeOS Router example.
*/
#include <service>
#include <net/router>
void Service::start()
{
auto& router = net::get_router();
auto& eth0 = net::Super_stack::get<net::IP4>(0);
auto& eth1 = net::Super_stack::get<net::IP4>(1);
eth0.set_forward_delg(router.forward_delg());
eth1.set_forward_delg(router.forward_delg());
}

View File

@ -0,0 +1,6 @@
{
"net" : [
{"device" : "virtio", "mac" : "c0:01:0a:00:00:2a"},
{"device" : "virtio", "mac" : "c0:01:0a:00:00:3a"}
]
}

View File

@ -0,0 +1,42 @@
cmake_minimum_required(VERSION 2.8.9)
if (NOT DEFINED ENV{INCLUDEOS_PREFIX})
set(ENV{INCLUDEOS_PREFIX} /usr/local)
endif()
include($ENV{INCLUDEOS_PREFIX}/includeos/pre.service.cmake)
project (WebServer)
# Human-readable name of your service
set(SERVICE_NAME "CETIC Unikernel Web Server")
# Name of your service binary
set(BINARY "WebServer")
# Source files to be linked with OS library parts to form bootable image
set(SOURCES
service.cpp # ...add more here
)
# To add your own include paths:
# set(LOCAL_INCLUDES ".")
# DRIVERS / PLUGINS:
set(DRIVERS
virtionet # Virtio networking
)
set(PLUGINS
autoconf
)
# STATIC LIBRARIES:
set(LIBRARIES
# path to full library
)
# include service build script
include($ENV{INCLUDEOS_PREFIX}/includeos/post.service.cmake)
# Create in-memory filesystem from folder
diskbuilder(disk)

View File

@ -0,0 +1,7 @@
#!/bin/bash
mkdir -p build
pushd build
cmake ..
make
popd

View File

@ -0,0 +1,13 @@
{
"net": [
{
"iface": 0,
"config": "static",
"address": "10.0.0.5",
"netmask": "255.255.255.0",
"gateway": "10.0.0.254"
}
]
}

View File

@ -0,0 +1,15 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>CETIC Internship Unikernel Web Page</title>
<link href="https://fonts.googleapis.com/css?family=Ubuntu:500,300" rel="stylesheet" type="text/css">
</head>
<body>
<h1 style="font-family: Arial, sans-serif">
CETIC Internship Unikernel Web Page
</h1>
<hr />
<p>This is the first web server spawn from a unikernel during the CETIC Intership 2017-18</p>
</body>
</html>

View File

@ -0,0 +1,47 @@
/*
* This code is adapted from the IncludeOS Acorn web server example.
*/
#include <service>
#include <net/inet4>
#include <net/http/server.hpp>
#include <memdisk>
std::unique_ptr<http::Server> server;
void Service::start()
{
// Retreive the stack (configured from outside)
auto& inet = net::Inet4::stack<0>();
Expects(inet.is_configured());
// Init the memdisk
auto& disk = fs::memdisk();
disk.init_fs([] (auto err, auto&) {
Expects(not err);
});
// Retreive the HTML page from the disk
auto file = disk.fs().read_file("/index.html");
Expects(file.is_valid());
net::tcp::buffer_t html(
new std::vector<uint8_t> (file.data(), file.data() + file.size()));
// Create a HTTP Server and setup request handling
server = std::make_unique<http::Server>(inet.tcp());
server->on_request([html] (auto req, auto rw)
{
// We only support get
if(req->method() != http::GET) {
rw->write_header(http::Not_Found);
return;
}
// Serve HTML on /
if(req->uri() == "/") {
rw->write(html);
} else {
rw->write_header(http::Not_Found);
}
});
// Start listening on port 80
server->listen(80);
}

View File

@ -0,0 +1,10 @@
<network>
<name>external</name>
<bridge name='virbr11' stp='on' delay='0'/>
<domain name='external'/>
<ip address='192.168.100.0' netmask='255.255.255.0'>
<dhcp>
<range start='192.168.100.100' end='192.168.100.200'/>
</dhcp>
</ip>
</network>

View File

@ -0,0 +1,6 @@
<network>
<name>firewall</name>
<bridge name='virbr12' stp='on' delay='0'/>
<domain name='firewall'/>
<ip address='192.168.101.1' netmask='255.255.255.248'/>
</network>

View File

@ -0,0 +1,10 @@
<network>
<name>internal</name>
<bridge name='virbr10' stp='on' delay='0'/>
<domain name='internal'/>
<ip address='10.0.0.1' netmask='255.255.255.0'>
<dhcp>
<range start='10.0.0.100' end='10.0.0.200'/>
</dhcp>
</ip>
</network>