TError TNlLink::AddVeth(const std::string &name, const std::string &hw, int mtu, int nsFd) { struct rtnl_link *veth, *peer; int ret; peer = rtnl_link_veth_alloc(); if (!peer) return TError(EError::Unknown, "Unable to allocate veth"); rtnl_link_set_name(peer, rtnl_link_get_name(Link)); veth = rtnl_link_veth_get_peer(peer); rtnl_link_set_name(veth, name.c_str()); if (nsFd >= 0) rtnl_link_set_ns_fd(veth, nsFd); if (mtu > 0) { rtnl_link_set_mtu(peer, mtu); rtnl_link_set_mtu(veth, mtu); } if (!hw.empty()) { TNlAddr addr; TError error = addr.Parse(AF_LLC, hw.c_str()); if (error) return error; rtnl_link_set_addr(veth, addr.Addr); } rtnl_link_set_flags(peer, IFF_UP); Dump("add", veth); rtnl_link_put(veth); Dump("add", peer); ret = rtnl_link_add(GetSock(), peer, NLM_F_CREATE | NLM_F_EXCL); if (ret < 0) { rtnl_link_put(peer); return Error(ret, "Cannot add veth"); } rtnl_link_put(peer); return Load(); }
int main(int argc, char *argv[]) { struct rtnl_link *link; struct nl_cache *link_cache; struct nl_sock *sk; struct nl_addr* addr; int err, master_index; sk = nl_socket_alloc(); if ((err = nl_connect(sk, NETLINK_ROUTE)) < 0) { nl_perror(err, "Unable to connect socket"); return err; } if ((err = rtnl_link_alloc_cache(sk, AF_UNSPEC, &link_cache)) < 0) { nl_perror(err, "Unable to allocate cache"); return err; } if (!(master_index = rtnl_link_name2i(link_cache, "eth0"))) { fprintf(stderr, "Unable to lookup eth0"); return -1; } link = rtnl_link_macvtap_alloc(); rtnl_link_set_link(link, master_index); addr = nl_addr_build(AF_LLC, ether_aton("00:11:22:33:44:55"), ETH_ALEN); rtnl_link_set_addr(link, addr); nl_addr_put(addr); rtnl_link_macvtap_set_mode(link, rtnl_link_macvtap_str2mode("bridge")); if ((err = rtnl_link_add(sk, link, NLM_F_CREATE)) < 0) { nl_perror(err, "Unable to add link"); return err; } rtnl_link_put(link); nl_close(sk); return 0; }