14
14
#include <unistd.h>
15
15
#include <libgen.h>
16
16
#include <sys/resource.h>
17
+ #include <sys/ioctl.h>
18
+ #include <sys/types.h>
19
+ #include <sys/socket.h>
20
+ #include <netinet/in.h>
17
21
18
22
#include "bpf_util.h"
19
23
#include <bpf/bpf.h>
22
26
static int ifindex_in ;
23
27
static int ifindex_out ;
24
28
static bool ifindex_out_xdp_dummy_attached = true;
29
+ static bool xdp_devmap_attached ;
25
30
static __u32 prog_id ;
26
31
static __u32 dummy_prog_id ;
27
32
@@ -83,31 +88,59 @@ static void poll_stats(int interval, int ifindex)
83
88
}
84
89
}
85
90
91
+ static int get_mac_addr (unsigned int ifindex_out , void * mac_addr )
92
+ {
93
+ char ifname [IF_NAMESIZE ];
94
+ struct ifreq ifr ;
95
+ int fd , ret = -1 ;
96
+
97
+ fd = socket (AF_INET , SOCK_DGRAM , 0 );
98
+ if (fd < 0 )
99
+ return ret ;
100
+
101
+ if (!if_indextoname (ifindex_out , ifname ))
102
+ goto err_out ;
103
+
104
+ strcpy (ifr .ifr_name , ifname );
105
+
106
+ if (ioctl (fd , SIOCGIFHWADDR , & ifr ) != 0 )
107
+ goto err_out ;
108
+
109
+ memcpy (mac_addr , ifr .ifr_hwaddr .sa_data , 6 * sizeof (char ));
110
+ ret = 0 ;
111
+
112
+ err_out :
113
+ close (fd );
114
+ return ret ;
115
+ }
116
+
86
117
static void usage (const char * prog )
87
118
{
88
119
fprintf (stderr ,
89
120
"usage: %s [OPTS] <IFNAME|IFINDEX>_IN <IFNAME|IFINDEX>_OUT\n\n"
90
121
"OPTS:\n"
91
122
" -S use skb-mode\n"
92
123
" -N enforce native mode\n"
93
- " -F force loading prog\n" ,
124
+ " -F force loading prog\n"
125
+ " -X load xdp program on egress\n" ,
94
126
prog );
95
127
}
96
128
97
129
int main (int argc , char * * argv )
98
130
{
99
131
struct bpf_prog_load_attr prog_load_attr = {
100
- .prog_type = BPF_PROG_TYPE_XDP ,
132
+ .prog_type = BPF_PROG_TYPE_UNSPEC ,
101
133
};
102
- struct bpf_program * prog , * dummy_prog ;
134
+ struct bpf_program * prog , * dummy_prog , * devmap_prog ;
135
+ int prog_fd , dummy_prog_fd , devmap_prog_fd = 0 ;
136
+ int tx_port_map_fd , tx_mac_map_fd ;
137
+ struct bpf_devmap_val devmap_val ;
103
138
struct bpf_prog_info info = {};
104
139
__u32 info_len = sizeof (info );
105
- int prog_fd , dummy_prog_fd ;
106
- const char * optstr = "FSN" ;
140
+ const char * optstr = "FSNX" ;
107
141
struct bpf_object * obj ;
108
142
int ret , opt , key = 0 ;
109
143
char filename [256 ];
110
- int tx_port_map_fd ;
111
144
112
145
while ((opt = getopt (argc , argv , optstr )) != -1 ) {
113
146
switch (opt ) {
@@ -120,14 +153,21 @@ int main(int argc, char **argv)
120
153
case 'F' :
121
154
xdp_flags &= ~XDP_FLAGS_UPDATE_IF_NOEXIST ;
122
155
break ;
156
+ case 'X' :
157
+ xdp_devmap_attached = true;
158
+ break ;
123
159
default :
124
160
usage (basename (argv [0 ]));
125
161
return 1 ;
126
162
}
127
163
}
128
164
129
- if (!(xdp_flags & XDP_FLAGS_SKB_MODE ))
165
+ if (!(xdp_flags & XDP_FLAGS_SKB_MODE )) {
130
166
xdp_flags |= XDP_FLAGS_DRV_MODE ;
167
+ } else if (xdp_devmap_attached ) {
168
+ printf ("Load xdp program on egress with SKB mode not supported yet\n" );
169
+ return 1 ;
170
+ }
131
171
132
172
if (optind == argc ) {
133
173
printf ("usage: %s <IFNAME|IFINDEX>_IN <IFNAME|IFINDEX>_OUT\n" , argv [0 ]);
@@ -150,24 +190,28 @@ int main(int argc, char **argv)
150
190
if (bpf_prog_load_xattr (& prog_load_attr , & obj , & prog_fd ))
151
191
return 1 ;
152
192
153
- prog = bpf_program__next (NULL , obj );
154
- dummy_prog = bpf_program__next (prog , obj );
155
- if (!prog || !dummy_prog ) {
156
- printf ("finding a prog in obj file failed\n" );
157
- return 1 ;
193
+ if (xdp_flags & XDP_FLAGS_SKB_MODE ) {
194
+ prog = bpf_object__find_program_by_name (obj , "xdp_redirect_map_general" );
195
+ tx_port_map_fd = bpf_object__find_map_fd_by_name (obj , "tx_port_general" );
196
+ } else {
197
+ prog = bpf_object__find_program_by_name (obj , "xdp_redirect_map_native" );
198
+ tx_port_map_fd = bpf_object__find_map_fd_by_name (obj , "tx_port_native" );
199
+ }
200
+ dummy_prog = bpf_object__find_program_by_name (obj , "xdp_redirect_dummy_prog" );
201
+ if (!prog || dummy_prog < 0 || tx_port_map_fd < 0 ) {
202
+ printf ("finding prog/dummy_prog/tx_port_map in obj file failed\n" );
203
+ goto out ;
158
204
}
159
- /* bpf_prog_load_xattr gives us the pointer to first prog's fd,
160
- * so we're missing only the fd for dummy prog
161
- */
205
+ prog_fd = bpf_program__fd (prog );
162
206
dummy_prog_fd = bpf_program__fd (dummy_prog );
163
- if (prog_fd < 0 || dummy_prog_fd < 0 ) {
207
+ if (prog_fd < 0 || dummy_prog_fd < 0 || tx_port_map_fd < 0 ) {
164
208
printf ("bpf_prog_load_xattr: %s\n" , strerror (errno ));
165
209
return 1 ;
166
210
}
167
211
168
- tx_port_map_fd = bpf_object__find_map_fd_by_name (obj , "tx_port " );
212
+ tx_mac_map_fd = bpf_object__find_map_fd_by_name (obj , "tx_mac " );
169
213
rxcnt_map_fd = bpf_object__find_map_fd_by_name (obj , "rxcnt" );
170
- if (tx_port_map_fd < 0 || rxcnt_map_fd < 0 ) {
214
+ if (tx_mac_map_fd < 0 || rxcnt_map_fd < 0 ) {
171
215
printf ("bpf_object__find_map_fd_by_name failed\n" );
172
216
return 1 ;
173
217
}
@@ -199,11 +243,39 @@ int main(int argc, char **argv)
199
243
}
200
244
dummy_prog_id = info .id ;
201
245
246
+ /* Load 2nd xdp prog on egress. */
247
+ if (xdp_devmap_attached ) {
248
+ unsigned char mac_addr [6 ];
249
+
250
+ devmap_prog = bpf_object__find_program_by_name (obj , "xdp_redirect_map_egress" );
251
+ if (!devmap_prog ) {
252
+ printf ("finding devmap_prog in obj file failed\n" );
253
+ goto out ;
254
+ }
255
+ devmap_prog_fd = bpf_program__fd (devmap_prog );
256
+ if (devmap_prog_fd < 0 ) {
257
+ printf ("finding devmap_prog fd failed\n" );
258
+ goto out ;
259
+ }
260
+
261
+ if (get_mac_addr (ifindex_out , mac_addr ) < 0 ) {
262
+ printf ("get interface %d mac failed\n" , ifindex_out );
263
+ goto out ;
264
+ }
265
+
266
+ ret = bpf_map_update_elem (tx_mac_map_fd , & key , mac_addr , 0 );
267
+ if (ret ) {
268
+ perror ("bpf_update_elem tx_mac_map_fd" );
269
+ goto out ;
270
+ }
271
+ }
272
+
202
273
signal (SIGINT , int_exit );
203
274
signal (SIGTERM , int_exit );
204
275
205
- /* populate virtual to physical port map */
206
- ret = bpf_map_update_elem (tx_port_map_fd , & key , & ifindex_out , 0 );
276
+ devmap_val .ifindex = ifindex_out ;
277
+ devmap_val .bpf_prog .fd = devmap_prog_fd ;
278
+ ret = bpf_map_update_elem (tx_port_map_fd , & key , & devmap_val , 0 );
207
279
if (ret ) {
208
280
perror ("bpf_update_elem" );
209
281
goto out ;
0 commit comments