1 /* Copyright (c) 2017 Covalent IO, Inc. http://covalent.io
3 * This program is free software; you can redistribute it and/or
4 * modify it under the terms of version 2 of the GNU General Public
5 * License as published by the Free Software Foundation.
7 * This program is distributed in the hope that it will be useful, but
8 * WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * General Public License for more details.
14 #include <sys/socket.h>
15 #include <sys/ioctl.h>
16 #include <sys/select.h>
17 #include <netinet/in.h>
18 #include <arpa/inet.h>
22 #include <sys/ioctl.h>
28 #include <sys/types.h>
30 #include <linux/netlink.h>
31 #include <linux/socket.h>
32 #include <linux/sock_diag.h>
33 #include <linux/bpf.h>
34 #include <linux/if_link.h>
38 #include "../bpf/bpf_load.h"
39 #include "../bpf/bpf_util.h"
40 #include "../bpf/libbpf.h"
43 void running_handler(int a
);
45 /* randomly selected ports for testing on lo */
49 static int sockmap_test_sockets(int rate
, int dot
)
51 int i
, sc
, err
, max_fd
, one
= 1;
52 int s1
, s2
, c1
, c2
, p1
, p2
;
53 struct sockaddr_in addr
;
54 struct timeval timeout
;
56 int *fds
[4] = {&s1
, &s2
, &c1
, &c2
};
59 s1
= s2
= p1
= p2
= c1
= c2
= 0;
62 for (i
= 0; i
< 4; i
++) {
63 *fds
[i
] = socket(AF_INET
, SOCK_STREAM
, 0);
65 perror("socket s1 failed()");
72 for (i
= 0; i
< 2; i
++) {
73 err
= setsockopt(*fds
[i
], SOL_SOCKET
, SO_REUSEADDR
,
74 (char *)&one
, sizeof(one
));
76 perror("setsockopt failed()");
81 /* Non-blocking sockets */
82 for (i
= 0; i
< 4; i
++) {
83 err
= ioctl(*fds
[i
], FIONBIO
, (char *)&one
);
85 perror("ioctl s1 failed()");
90 /* Bind server sockets */
91 memset(&addr
, 0, sizeof(struct sockaddr_in
));
92 addr
.sin_family
= AF_INET
;
93 addr
.sin_addr
.s_addr
= inet_addr("127.0.0.1");
95 addr
.sin_port
= htons(S1_PORT
);
96 err
= bind(s1
, (struct sockaddr
*)&addr
, sizeof(addr
));
98 perror("bind s1 failed()\n");
102 addr
.sin_port
= htons(S2_PORT
);
103 err
= bind(s2
, (struct sockaddr
*)&addr
, sizeof(addr
));
105 perror("bind s2 failed()\n");
109 /* Listen server sockets */
110 addr
.sin_port
= htons(S1_PORT
);
111 err
= listen(s1
, 32);
113 perror("listen s1 failed()\n");
117 addr
.sin_port
= htons(S2_PORT
);
118 err
= listen(s2
, 32);
120 perror("listen s1 failed()\n");
124 /* Initiate Connect */
125 addr
.sin_port
= htons(S1_PORT
);
126 err
= connect(c1
, (struct sockaddr
*)&addr
, sizeof(addr
));
127 if (err
< 0 && errno
!= EINPROGRESS
) {
128 perror("connect c1 failed()\n");
132 addr
.sin_port
= htons(S2_PORT
);
133 err
= connect(c2
, (struct sockaddr
*)&addr
, sizeof(addr
));
134 if (err
< 0 && errno
!= EINPROGRESS
) {
135 perror("connect c2 failed()\n");
139 /* Accept Connecrtions */
140 p1
= accept(s1
, NULL
, NULL
);
142 perror("accept s1 failed()\n");
146 p2
= accept(s2
, NULL
, NULL
);
148 perror("accept s1 failed()\n");
156 printf("connected sockets: c1 <-> p1, c2 <-> p2\n");
157 printf("cgroups binding: c1(%i) <-> s1(%i) - - - c2(%i) <-> s2(%i)\n",
160 /* Ping/Pong data from client to server */
161 sc
= send(c1
, buf
, sizeof(buf
), 0);
163 perror("send failed()\n");
177 s
= select(max_fd
+ 1, &w
, NULL
, NULL
, &timeout
);
182 fprintf(stderr
, "unexpected timeout\n");
186 for (i
= 0; i
<= max_fd
&& s
> 0; ++i
) {
187 if (!FD_ISSET(i
, &w
))
192 rc
= recv(i
, buf
, sizeof(buf
), 0);
194 if (errno
!= EWOULDBLOCK
) {
195 perror("recv failed()\n");
205 sc
= send(i
, buf
, rc
, 0);
207 perror("send failed()\n");
229 int main(int argc
, char **argv
)
231 int rate
= 1, dot
= 1;
236 cg_path
= argv
[argc
- 1];
237 snprintf(filename
, sizeof(filename
), "%s_kern.o", argv
[0]);
242 signal(SIGINT
, running_handler
);
244 if (load_bpf_file(filename
)) {
245 fprintf(stderr
, "load_bpf_file: (%s) %s\n",
246 filename
, strerror(errno
));
250 /* Cgroup configuration */
251 cg_fd
= open(cg_path
, O_DIRECTORY
, O_RDONLY
);
253 fprintf(stderr
, "ERROR: (%i) open cg path failed: %s\n",
258 /* Attach programs to sockmap */
259 err
= bpf_prog_attach(prog_fd
[0], map_fd
[0],
260 BPF_SK_SKB_STREAM_PARSER
, 0);
262 fprintf(stderr
, "ERROR: bpf_prog_attach (sockmap): %d (%s)\n",
263 err
, strerror(errno
));
267 err
= bpf_prog_attach(prog_fd
[1], map_fd
[0],
268 BPF_SK_SKB_STREAM_VERDICT
, 0);
270 fprintf(stderr
, "ERROR: bpf_prog_attach (sockmap): %d (%s)\n",
271 err
, strerror(errno
));
275 /* Attach to cgroups */
276 err
= bpf_prog_attach(prog_fd
[2], cg_fd
, BPF_CGROUP_SOCK_OPS
, 0);
278 fprintf(stderr
, "ERROR: bpf_prog_attach (groups): %d (%s)\n",
279 err
, strerror(errno
));
283 err
= sockmap_test_sockets(rate
, dot
);
285 fprintf(stderr
, "ERROR: test socket failed: %d\n", err
);
291 void running_handler(int a
)