Skip to content

Commit

Permalink
lkl: lkl_add_arp_entry
Browse files Browse the repository at this point in the history
Provides API support to add permanent arp entries to lkl so outsiders
don't need to reply arp request.

Signed-off-by: Yuan Liu <liuyuan@google.com>
  • Loading branch information
liuyuan10 committed Jun 18, 2016
1 parent e9c3b4a commit e2a4010
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 2 deletions.
9 changes: 8 additions & 1 deletion Documentation/lkl.txt
Original file line number Diff line number Diff line change
Expand Up @@ -189,9 +189,16 @@ are the list of those variable for your environment.
```
$ LKL_HIJACK_NET_MTU=1280 lkl-hijack.sh ip address show
```
* LKL_HIJACK_NET_ARP

Add a list of arp permanent entries in the form of "ip|mac;ip|mac;..."
```
$ LKL_HIJACK_NET_ARP="192.168.13.100|12:34:56:78:9a:bc;192.168.13.101|12:34:56:78:9a:be"
lkl-hijack.sh ip neighbor show
```
* LKL_HIJACK_DEBUG

increate the verbose level of debug information.
increase the verbose level of debug information.
```
$ LKL_HIJACK_DEBUG=1 lkl-hijack.sh ip address show
```
Expand Down
8 changes: 8 additions & 0 deletions tools/lkl/include/lkl.h
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,14 @@ struct lkl_netdev *lkl_netdev_dpdk_create(const char *ifname);
*/
struct lkl_netdev *lkl_netdev_vde_create(const char *switch_path);

/**
* lkl_add_arp_entry - add a permanent arp entry
* @ifindex - the ifindex of the interface
* @ip - ip address of the entry in network byte order
* @mac - mac address of the entry
*/
int lkl_add_arp_entry(int ifindex, unsigned int ip, void* mac);

#ifdef __cplusplus
}
#endif
Expand Down
33 changes: 33 additions & 0 deletions tools/lkl/lib/hijack/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,35 @@ int parse_mac_str(char *mac_str, __lkl__u8 mac[LKL_ETH_ALEN])
return 1;
}

/* Add permanent arp entries in the form of "ip|mac;ip|mac;..." */
static void add_arp(int ifindex, char* entries) {
char *saveptr = NULL, *token = NULL;
char *ip = NULL, *mac_str = NULL;
int ret = 0;
__lkl__u8 mac[LKL_ETH_ALEN];
unsigned int ip_addr;

for (token = strtok_r(entries, ";", &saveptr); token;
token = strtok_r(NULL, ";", &saveptr)) {
ip = strtok(token, "|");
mac_str = strtok(NULL, "|");
if (ip == NULL || mac_str == NULL || strtok(NULL, "|") != NULL) {
return;
}
ip_addr = inet_addr(ip);
ret = parse_mac_str(mac_str, mac);
if (ret != 1) {
fprintf(stderr, "Failed to parse mac: %s\n", mac_str);
return;
}
ret = lkl_add_arp_entry(ifindex, ip_addr, mac);
if (ret) {
fprintf(stderr, "Failed to add arp entry: %s\n", lkl_strerror(ret));
return;
}
}
return;
}

/* We don't have an easy way to make FILE*s out of our fds, so we
* can't use e.g. fgets */
Expand Down Expand Up @@ -165,6 +194,7 @@ hijack_init(void)
char *debug = getenv("LKL_HIJACK_DEBUG");
char *mount = getenv("LKL_HIJACK_MOUNT");
struct lkl_netdev *nd = NULL;
char *arp_entries = getenv("LKL_HIJACK_NET_ARP");

/* Must be run before lkl_netdev_tap_create */
fixup_netdev_tap_ops();
Expand Down Expand Up @@ -272,6 +302,9 @@ hijack_init(void)

if (mount)
mount_cmds_exec(mount, mount_fs);

if (nd_ifindex >=0 && arp_entries)
add_arp(nd_ifindex, arp_entries);
}

void __attribute__((destructor))
Expand Down
43 changes: 42 additions & 1 deletion tools/lkl/lib/net.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
#include "endian.h"
#include <lkl_host.h>


static inline void set_sockaddr(struct lkl_sockaddr_in *sin, unsigned int addr,
unsigned short port)
{
Expand Down Expand Up @@ -159,3 +158,45 @@ int lkl_netdev_get_ifindex(int id)

return ret < 0 ? ret : ifr.lkl_ifr_ifindex;
}

struct lkl_arpreq {
struct lkl_sockaddr arp_pa; /* protocol address */
struct lkl_sockaddr arp_ha; /* hardware address */
int arp_flags; /* flags */
struct lkl_sockaddr arp_netmask; /* netmask of protocol address */
char arp_dev[LKL_IFNAMSIZ];
};

#define LKL_ATF_PERM 0x04
#define LKL_ATF_COM 0x02

int lkl_add_arp_entry(int ifindex, unsigned int ip, void* mac) {
struct lkl_arpreq req;
int ret = 0;
struct lkl_ifreq ifr;
struct lkl_sockaddr_in* sin = (struct lkl_sockaddr_in*)&req.arp_pa;
int sock;

bzero(&req, sizeof(req));
sin->sin_family = LKL_AF_INET;
sin->sin_addr.lkl_s_addr = ip;
memcpy(req.arp_ha.sa_data, mac, LKL_ETH_ALEN);

sock = lkl_sys_socket(LKL_AF_INET, LKL_SOCK_DGRAM, 0);
if (sock < 0) {
return sock;
}

req.arp_flags = LKL_ATF_PERM | LKL_ATF_COM;

ret = ifindex_to_name(sock, &ifr, ifindex);
if (ret < 0) {
lkl_sys_close(sock);
return ret;
}
strcpy(req.arp_dev, ifr.ifr_ifrn.ifrn_name);

ret = lkl_sys_ioctl(sock, LKL_SIOCSARP, (long)(&req));
lkl_sys_close(sock);
return ret;
}
7 changes: 7 additions & 0 deletions tools/lkl/tests/hijack-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,13 @@ sudo arp -d 192.168.13.2
sudo ping -i 0.01 -c 65 192.168.13.2 &
${hijack_script} sleep 3

# add arp entries
ans=$(LKL_HIJACK_NET_ARP="192.168.13.100|12:34:56:78:9a:bc;192.168.13.101|12:34:56:78:9a:be"\
${hijack_script} ip neighbor show) || true
echo "$ans" | tail -n 15 | grep "12:34:56:78:9a:bc"
echo "$ans" | tail -n 15 | grep "12:34:56:78:9a:be"


sh ${script_dir}/run_netperf.sh 192.168.13.1 1 0 TCP_STREAM
sh ${script_dir}/run_netperf.sh 192.168.13.1 1 0 TCP_RR

Expand Down

0 comments on commit e2a4010

Please sign in to comment.