summaryrefslogtreecommitdiffstats
path: root/docs/source/apps.md
blob: eefb68be1e0ef64bc8d3f27e1846f51893f9d9a8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
# Application examples using hICN stack

## Introduction

higet and hicn-http-proxy are two application examples that use hicn stack.

## Using hICN Application Examples

### Dependencies

Build dependencies:

- c++14 ( clang++ / g++ )
- CMake 3.5 or higher

Basic dependencies:

- OpenSSL
- pthreads
- libevent
- libparc
- libcurl
- libhicntransport

## Executables

### hicn-http-proxy

`hicn-http-proxy` is a reverse proxy which can be used for augmenting the performance of a legacy HTTP/TCP server
by making use of hICN. It performs the following operations:

- Receives a HTTP request from a hICN client
- Forwards it to a HTTP server over TCP
- Receives the response from the server and send it back to the client

```bash
hicn-http-proxy [HTTP_PREFIX] [OPTIONS]

HTTP_PREFIX: The prefix used for building the hicn names.

Options:
-a <server_address>   = origin server address
-p <server_port>      = origin server port
-c <cache_size>       = cache size of the proxy, in number of hicn data packets
-m <mtu>              = mtu of hicn packets
-P <prefix>           = optional most significant 16 bits of hicn prefix, in hexadecimal format

Example:
./hicn-http-proxy http://webserver -a 127.0.0.1 -p 8080 -c 10000 -m 1200 -P b001
```

The hICN names used by the hicn-http-proxy for naming the HTTP responses are composed in the following way,
starting from the most significant byte:

- The first 2 bytes are the prefix specified in the -P option
- The next 6 bytes are the hash (Fowler–Noll–Vo non-crypto hash) of the locator (in the example `webserver`, without the `http://` part)
- The last 8 bytes are the hash (Fowler–Noll–Vo non-crypto hash) of the http request corresponding to the response being forwarded back to the client.

### higet

Higet is a non-interactive HTTP client working on top oh hICN.

```bash
higet [option]... [url]
Options:
-O <output_path>            = write documents to <output_file>. Use '-' for stdout.
-S                          = print server response.
-P                          = optional first 16 bits of hicn prefix, in hexadecimal format

Example:
./higet -P b001 -O - http://webserver/index.html
```

The hICN names used by higet for naming the HTTP requests are composed the same way as described in [hicn-http-proxy](#hicn-http-proxy).

### How To Setup A Simple HTTP Client-Server Scenario using the hicn-http-proxy

We consider the following topology, consisting on two linux VM which are able to communicate through an IP network (you can also use containers or physical machines):

```text
|client (10.0.0.1/24; 9001::1/64)|======|server (10.0.0.2/24; 9001::2/64)|
```

Install the hICN suite on two linux VM. This tutorial makes use of Ubuntu 18.04, but it could easily be adapted to other platforms.
You can either install the hICN stack using binaries or compile the code. In this tutorial we will make use of docker container and binaries packages.

The client will use of the hicn-light forwarder, which is lightweight and tailored for devices such as android and laptops.
The server will use the hicn-plugin of vpp, which guarantees better performances and it is the best choice for server applications.

Keep in mind that on the same system the stack based on vpp forwarder cannot coexist with the stack based on hicn light.

For running the hicn-plugin at the server there are two main alternatives:

- Use a docker container
- Run the hicn-plugin directly in a VM or Bare Metal Server

#### Docker

Install docker in the server VM:

```bash
server$ sudo apt-get update
server$ sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg-agent \
    software-properties-common

server$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
server$ sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"
server$ sudo apt-get update
server$ sudo apt-get install docker-ce docker-ce-cli containerd.io
```

Run the hicn-http-proxy container. Here we use a public server [example.com](example.com) as origin:

```bash
server$ docker run -e ORIGIN_ADDRESS=example.com    \
             -e ORIGIN_PORT=80                      \
             -e CACHE_SIZE=10000                    \
             -e HICN_MTU=1200                       \
             -e FIRST_IPV6_WORD=c001                \
             -e HICN_PREFIX=http://webserver        \
             --privileged                           \
             --name vhttpproxy                      \
             -d icnteam/vhttpproxy
```

Create a hicn private network:

```bash
server$ GATEWAY=192.168.0.254
server$ docker network create --subnet 192.168.0.0/24 --gateway ${GATEWAY} hicn-network
```

Connect the proxy container to the hicn network:

```bash
server$ docker network connect hicn-network vhttpproxy
```

Connect the hicn network to the vpp forwarder:

```bash
server$ IP_ADDRESS=$(docker inspect -f "{{with index .NetworkSettings.Networks \"hicn-network\"}}{{.IPAddress}}{{end}}" vhttpproxy)
server$ INTERFACE=$(docker exec -it vhttpproxy ifconfig | grep -B 1 ${IP_ADDRESS} | awk 'NR==1 {gsub(":","",$1); print $1}')
server$ docker exec -it vhttpproxy ip addr flush dev ${INTERFACE}
server$ docker exec -it vhttpproxy ethtool -K ${INTERFACE} tx off rx off ufo off gso off gro off tso off
server$ docker exec -it vhttpproxy vppctl create host-interface name ${INTERFACE}
server$ docker exec -it vhttpproxy vppctl set interface state host-${INTERFACE} up
server$ docker exec -it vhttpproxy vppctl set interface ip address host-${INTERFACE} ${IP_ADDRESS}/24
server$ docker exec -it vhttpproxy vppctl ip route add 10.0.0.0/24 via ${GATEWAY} host-eth1
```

Set the punting:

```bash
server$ PORT=12345
server$ docker exec -it vhttpproxy vppctl hicn punting add prefix c001::/16 intfc host-${INTERFACE} type udp4 src_port ${PORT} dst_port ${PORT}
```

Docker containers are cool, but sometimes they do not allow you to do simple operations like expose ports while the container is already running. But we have a workaround for this :)

```bash
server$ sudo iptables -t nat -A DOCKER -p udp --dport ${PORT} -j DNAT --to-destination ${IP_ADDRESS}:${PORT}
server$ sudo iptables -t nat -A POSTROUTING -j MASQUERADE -p udp --source ${IP_ADDRESS} --destination ${IP_ADDRESS} --dport ${PORT}
server$ sudo iptables -A DOCKER -j ACCEPT -p udp --destination ${IP_ADDRESS} --dport ${PORT}
```

In the client, install the hicn stack:

```bash
client$ sudo apt-get install -y hicn-light hicn-apps
```

Create a configuration file for the hicn-light forwarder. Here we are configuring UDP faces:

```bash
client$ mkdir -p ${HOME}/etc
client$ LOCAL_IP="10.0.0.2" # Put here the actual IPv4 of the local interface
client$ LOCAL_PORT="12345"
client$ REMOTE_IP="10.0.0.1" # Put here the actual IPv4 of the remote interface
client$ REMOTE_PORT="12345"
client$ cat << EOF > ${HOME}/etc/hicn-light.conf
add listener udp list0 ${LOCAL_IP} ${LOCAL_PORT}
add connection udp conn0 ${REMOTE_IP} ${REMOTE_PORT} ${LOCAL_IP} ${LOCAL_PORT}
add route conn0 c001::/16 1
EOF
```

Run the hicn-light forwarder

```bash
client$ sudo /usr/bin/hicn-light-daemon --daemon --capacity 1000 --log-file ${HOME}/hicn-light.log --config ${HOME}/etc/hicn-light.conf
```

Run the http client [higet](#higet) and print the http response on stdout:

```bash
client$ /usr/bin/higet -O - http://webserver/index.html -P c001
```

#### Host/VM

You can install the hicn-plugin of vpp on your VM and directly use DPDK compatible nics, forwarding hicn packets directly over the network. DPDK compatible nics can be used inside a container as well.

```bash
server$ sudo apt-get install -y hicn-plugin vpp-plugin-dpdk hicn-apps-memif
```

It will install all the required deps (vpp, hicn apps and libraries compiled for communicating with vpp using shared memories). Configure VPP following the steps described [here](https://github.com/FDio/hicn/blob/master/hicn-plugin/README.md#configure-vpp).

This tutorial assumes you configured two interfaces in your server VM:

- One interface which uses the DPDK driver, to be used by VPP
- One interface which is still owned by the kernel

The DPDK interface will be used for connecting the server with the hicn client, while the other interface will guarantee connectivity to the applications running in the VM, including the hicn-http-proxy. If you run the commands:

```bash
server$ sudo systemctl restart vpp
server$ vppctl show int
```

The output must show the dpdk interface owned by VPP:

```text
              Name               Idx    State  MTU (L3/IP4/IP6/MPLS)     Counter          Count
GigabitEthernetb/0/0              1     down         9000/0/0/0
local0                            0     down          0/0/0/0
```

If the interface is down, bring it up and assign the correct ip address to it:

```bash
server$ vppctl set int state GigabitEthernetb/0/0 up
server$ vppctl set interface ip address GigabitEthernetb/0/0 9001::1/64
```

Take care of replacing the interface name (`GigabitEthernetb/0/0`) with the actual name of your interface.

Now enable the hicn plugin and set the punting for the hicn packets:

```bash
server$ vppctl hicn control start
server$ vppctl hicn punting add prefix c001::/16 intfc GigabitEthernetb/0/0 type ip
```

Run the hicn-http-proxy app:

```bash
server$ sudo /usr/bin/hicn-http-proxy -a example.com -p 80 -c 10000 -m 1200 -P c001 http://webserver
```

Configure the client for sending hicn packets without any udp encapsulation:

```bash
client$ mkdir -p ${HOME}/etc
client$ LOCAL_IP="9001::2"
client$ REMOTE_IP="9001::1"
client$ cat << EOF > ${HOME}/etc/hicn-light.conf
add listener hicn lst 0::0
add punting lst c001::/16
add listener hicn list0 ${LOCAL_IP}
add connection hicn conn0 ${REMOTE_IP} ${LOCAL_IP}
add route conn0 c001::/16 1
EOF
```

Restart the forwarder:

```bash
client$ sudo killall -INT hicn-light-daemon
client$ sudo /usr/bin/hicn-light-daemon --daemon --capacity 1000 --log-file ${HOME}/hicn-light.log --config ${HOME}/etc/hicn-light.conf
```

Retrieve a web page:

```bash
client$ /usr/bin/higet -O - http://webserver/index.html -P c001
```

## License

This software is distributed under the following license:

```text
Copyright (c) 2017-2019 Cisco and/or its affiliates.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at:

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
```