Skip to content

Commit

Permalink
Merge pull request torvalds#166 from liuyuan10/arp
Browse files Browse the repository at this point in the history
lkl: lkl_add_arp_entry
  • Loading branch information
Octavian Purdila committed Jun 18, 2016
2 parents 0e1679b + e2a4010 commit 6dacb1e
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 @@ -312,6 +312,14 @@ struct lkl_netdev *lkl_netdev_vde_create(const char *switch_path);
*/
void lkl_register_dbg_handler();

/**
* 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 @@ -273,6 +303,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 6dacb1e

Please sign in to comment.