Hi, Few minor suggestions, if you care.
On Tue, Apr 8, 2014 at 5:22 AM, Susant Sahani <sus...@redhat.com> wrote: > This patch enables basic ipip tunnel support. > It works with kernel module ipip > > Example configuration > > file: ipip.netdev > -------------------------- > [NetDev] > Name=ipip-tun > Kind=ipip > > [Tunnel] > Local=192.168.8.102 > Remote=10.4.4.4 > TTL=64 > MTUBytes=1480 > > file: ipip.network > -------------------------- > [Match] > Name=eth0 > > [Network] > Tunnel=ipip-tun > --- > Makefile.am | 7 +- > src/libsystemd-network/network-internal.c | 33 ++++++ > src/libsystemd-network/network-internal.h | 3 + > src/libsystemd/sd-rtnl/rtnl-types.c | 4 +- > src/network/networkd-link.c | 25 ++++- > src/network/networkd-manager.c | 14 +++ > src/network/networkd-netdev-gperf.gperf | 4 + > src/network/networkd-netdev.c | 169 > +++++++++++++++++++++++++++++- > src/network/networkd-network-gperf.gperf | 1 + > src/network/networkd-network.c | 37 +++++++ > src/network/networkd.c | 6 ++ > src/network/networkd.h | 27 +++++ > 12 files changed, 323 insertions(+), 7 deletions(-) > > diff --git a/Makefile.am b/Makefile.am > index c51f6ae..60c7016 100644 > --- a/Makefile.am > +++ b/Makefile.am > @@ -4144,8 +4144,8 @@ systemd_networkd_SOURCES = \ > src/network/networkd.c > > systemd_networkd_LDADD = \ > - libsystemd-networkd-core.la > - > + libsystemd-networkd-core.la \ > + -lkmod > noinst_LTLIBRARIES += \ > libsystemd-networkd-core.la > > @@ -4189,7 +4189,8 @@ test_network_SOURCES = \ > src/network/test-network.c > > test_network_LDADD = \ > - libsystemd-networkd-core.la > + libsystemd-networkd-core.la \ > + -lkmod > > tests += \ > test-network > diff --git a/src/libsystemd-network/network-internal.c > b/src/libsystemd-network/network-internal.c > index 3686267..5b41cdb 100644 > --- a/src/libsystemd-network/network-internal.c > +++ b/src/libsystemd-network/network-internal.c > @@ -326,3 +326,36 @@ int net_parse_inaddr(const char *address, unsigned char > *family, void *dst) { > > return 0; > } > + > +int load_module(struct kmod_ctx *ctx, const char *mod_name) { > + struct kmod_list *modlist = NULL, *l; > + int r; > + > + assert(ctx); > + assert(mod_name); > + > + r = kmod_module_new_from_lookup(ctx, mod_name, &modlist); > + if (r < 0) > + return r; > + > + if (!modlist) { > + log_error("Failed to find module '%s'", mod_name); > + return -ENOENT; > + } > + > + kmod_list_foreach(l, modlist) { > + struct kmod_module *mod = kmod_module_get_module(l); Small optimization but maybe move stuct kmod_module *mod; outside of the for each. > + > + r = kmod_module_probe_insert_module(mod, 0, NULL, NULL, > NULL, NULL); If r is "-1" from previous run, we are overriding it here. > + if (r >= 0) > + r = 0; > + else > + r = -1; > + > + kmod_module_unref(mod); > + } > + > + kmod_module_unref_list(modlist); > + > + return r; > +} > diff --git a/src/libsystemd-network/network-internal.h > b/src/libsystemd-network/network-internal.h > index 65cd0d7..28f53b9 100644 > --- a/src/libsystemd-network/network-internal.h > +++ b/src/libsystemd-network/network-internal.h > @@ -24,6 +24,7 @@ > #include <netinet/ether.h> > #include <netinet/in.h> > #include <stdbool.h> > +#include <libkmod.h> > > #include "udev.h" > #include "condition-util.h" > @@ -65,3 +66,5 @@ int config_parse_ifalias(const char *unit, const char > *filename, unsigned line, > int net_parse_inaddr(const char *address, unsigned char *family, void *dst); > > int net_get_unique_predictable_data(struct udev_device *device, uint8_t > result[8]); > + > +int load_module(struct kmod_ctx *ctx, const char *mod_name); > diff --git a/src/libsystemd/sd-rtnl/rtnl-types.c > b/src/libsystemd/sd-rtnl/rtnl-types.c > index 44ac5ec..96467a3 100644 > --- a/src/libsystemd/sd-rtnl/rtnl-types.c > +++ b/src/libsystemd/sd-rtnl/rtnl-types.c > @@ -104,8 +104,8 @@ static const NLType > rtnl_link_info_data_bond_types[IFLA_BOND_MAX + 1] = { > > static const NLType rtnl_link_info_data_iptun_types[IFLA_IPTUN_MAX + 1] = { > [IFLA_IPTUN_LINK] = { .type = NLA_U32 }, > - [IFLA_IPTUN_LOCAL] = { .type = NLA_U32 }, > - [IFLA_IPTUN_REMOTE] = { .type = NLA_U32 }, > + [IFLA_IPTUN_LOCAL] = { .type = NLA_IN_ADDR }, > + [IFLA_IPTUN_REMOTE] = { .type = NLA_IN_ADDR }, > [IFLA_IPTUN_TTL] = { .type = NLA_U8 }, > [IFLA_IPTUN_TOS] = { .type = NLA_U8 }, > [IFLA_IPTUN_PMTUDISC] = { .type = NLA_U8 }, > diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c > index 63d253d..848eddd 100644 > --- a/src/network/networkd-link.c > +++ b/src/network/networkd-link.c > @@ -1207,7 +1207,9 @@ static int link_enter_enslave(Link *link) { > > link_save(link); > > - if (!link->network->bridge && !link->network->bond && > + if (!link->network->bridge && > + !link->network->bond && > + !link->network->tunnel && > hashmap_isempty(link->network->vlans) && > hashmap_isempty(link->network->macvlans)) > return link_enslaved(link); > @@ -1254,6 +1256,27 @@ static int link_enter_enslave(Link *link) { > link->enslaving ++; > } > > + if (link->network->tunnel) { > + log_struct_link(LOG_DEBUG, link, > + "MESSAGE=%s: enslaving by '%s'", > + link->ifname, link->network->tunnel->name, > + NETDEV(link->network->tunnel), > + NULL); > + > + r = netdev_enslave(link->network->tunnel, link, > &enslave_handler); > + if (r < 0) { > + log_struct_link(LOG_WARNING, link, > + "MESSAGE=%s: could not enslave by > '%s': %s", > + link->ifname, > link->network->tunnel->name, strerror(-r), > + NETDEV(link->network->tunnel), > + NULL); > + link_enter_failed(link); > + return r; > + } > + > + link->enslaving ++; > + } > + > HASHMAP_FOREACH(vlan, link->network->vlans, i) { > log_struct_link(LOG_DEBUG, link, > "MESSAGE=%s: enslaving by '%s'", > diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c > index d903d0d..7e48ab0 100644 > --- a/src/network/networkd-manager.c > +++ b/src/network/networkd-manager.c > @@ -20,6 +20,7 @@ > ***/ > > #include <resolv.h> > +#include <libkmod.h> > > #include "path-util.h" > #include "networkd.h" > @@ -158,6 +159,8 @@ void manager_free(Manager *m) { > > sd_rtnl_unref(m->rtnl); > > + kmod_unref(m->kmod_ctx); > + > free(m); > } > > @@ -467,3 +470,14 @@ int manager_update_resolv_conf(Manager *m) { > > return 0; > } > + > +int manager_init_kmod_ctx(Manager *m) { > + assert(m); > + > + m->kmod_ctx = kmod_new(NULL, NULL); > + if (!m->kmod_ctx) { > + return -ENOMEM; > + } > + > + return 0; > +} > diff --git a/src/network/networkd-netdev-gperf.gperf > b/src/network/networkd-netdev-gperf.gperf > index ea7ba57..fad828f 100644 > --- a/src/network/networkd-netdev-gperf.gperf > +++ b/src/network/networkd-netdev-gperf.gperf > @@ -24,3 +24,7 @@ NetDev.Name, config_parse_ifname, > 0, > NetDev.Kind, config_parse_netdev_kind, 0, > offsetof(NetDev, kind) > VLAN.Id, config_parse_uint64, 0, > offsetof(NetDev, vlanid) > MACVLAN.Mode, config_parse_macvlan_mode, 0, > offsetof(NetDev, macvlan_mode) > +Tunnel.TTL, config_parse_int, 0, > offsetof(NetDev, tunnel_ttl) > +Tunnel.MTUBytes, config_parse_int, 0, > offsetof(NetDev, tunnel_mtu) > +Tunnel.Local, config_parse_tunnel_address, 0, > offsetof(NetDev, tunnel_local) > +Tunnel.Remote, config_parse_tunnel_address, 0, > offsetof(NetDev, tunnel_remote) > diff --git a/src/network/networkd-netdev.c b/src/network/networkd-netdev.c > index 92548d9..b9a2334 100644 > --- a/src/network/networkd-netdev.c > +++ b/src/network/networkd-netdev.c > @@ -18,6 +18,12 @@ > You should have received a copy of the GNU Lesser General Public License > along with systemd; If not, see <http://www.gnu.org/licenses/>. > ***/ > +#include <netinet/ether.h> > +#include <arpa/inet.h> > +#include <net/if.h> > +#include <linux/ip.h> > +#include <linux/if_tunnel.h> > +#include <libkmod.h> > > #include "networkd.h" > #include "network-internal.h" > @@ -33,6 +39,9 @@ static const char* const > netdev_kind_table[_NETDEV_KIND_MAX] = { > [NETDEV_KIND_BOND] = "bond", > [NETDEV_KIND_VLAN] = "vlan", > [NETDEV_KIND_MACVLAN] = "macvlan", > + [NETDEV_KIND_IPIP] = "ipip", > + [NETDEV_KIND_GRE] = "gre", > + [NETDEV_KIND_SIT] = "sit", > }; > > DEFINE_STRING_TABLE_LOOKUP(netdev_kind, NetDevKind); > @@ -242,6 +251,159 @@ static int netdev_create_handler(sd_rtnl *rtnl, > sd_rtnl_message *m, void *userda > return 1; > } > > +int config_parse_tunnel_address(const char *unit, > + const char *filename, > + unsigned line, > + const char *section, > + unsigned section_line, > + const char *lvalue, > + int ltype, > + const char *rvalue, > + void *data, > + void *userdata) { > + struct in_addr *n = data; > + unsigned char family = AF_INET; > + int r; > + > + assert(filename); > + assert(lvalue); > + assert(rvalue); > + assert(data); > + > + r = net_parse_inaddr(rvalue, &family, n); > + if (r < 0) { > + log_syntax(unit, LOG_ERR, filename, line, EINVAL, > + "Tunnel address is invalid, ignoring assignment: > %s", rvalue); > + return 0; > + } > + > + return 0; > +} > + > +int netdev_create_tunnel(Link *link) { > + _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL; > + NetDev *netdev; > + int r; > + > + assert(link); > + assert(link->network); > + assert(link->network->tunnel); > + > + netdev = link->network->tunnel; > + > + assert(netdev); > + assert(netdev->name); > + assert(netdev->manager); > + assert(netdev->manager->rtnl); > + assert(netdev->manager->kmod_ctx); > + > + if(netdev->kind == NETDEV_KIND_IPIP || > + netdev->kind == NETDEV_KIND_GRE || > + netdev->kind == NETDEV_KIND_SIT) { > + r = load_module(netdev->manager->kmod_ctx, > netdev_kind_to_string(netdev->kind)); > + if (r < 0) { > + log_error_netdev(netdev, "Could not load Kernel > module . Ignoring"); > + return 0; > + } > + } > + > + r = sd_rtnl_message_new_link(netdev->manager->rtnl, &m, RTM_NEWLINK, > 0); > + if (r < 0) { > + log_error_netdev(netdev, > + "Could not allocate RTM_NEWLINK message: > %s", > + strerror(-r)); > + return r; > + } > + > + r = sd_rtnl_message_append_string(m, IFLA_IFNAME, netdev->name); > + if (r < 0) { > + log_error_netdev(netdev, > + "Could not append IFLA_IFNAME, attribute: > %s", > + strerror(-r)); > + return r; > + } > + > + if(netdev->tunnel_mtu) { > + r = sd_rtnl_message_append_u32(m, IFLA_MTU, > netdev->tunnel_mtu); > + if (r < 0) { > + log_error_netdev(netdev, > + "Could not append IFLA_MTU > attribute: %s", > + strerror(-r)); > + return r; > + } > + } > + > + r = sd_rtnl_message_open_container(m, IFLA_LINKINFO); > + if (r < 0) { > + log_error_netdev(netdev, > + "Could not append IFLA_LINKINFO attribute: > %s", > + strerror(-r)); > + return r; > + } > + > + r = sd_rtnl_message_open_container_union(m, IFLA_INFO_DATA, > + > netdev_kind_to_string(netdev->kind)); > + if (r < 0) { > + log_error_netdev(netdev, > + "Could not append IFLA_INFO_DATA attribute: > %s", > + strerror(-r)); > + return r; > + } > + > + r = sd_rtnl_message_append_u32(m, IFLA_IPTUN_LINK, link->ifindex); > + if (r < 0) { > + log_error_netdev(netdev, > + "Could not append IFLA_IPTUN_LINK > attribute: %s", > + strerror(-r)); > + return r; > + } > + > + r= sd_rtnl_message_append_in_addr(m, IFLA_IPTUN_LOCAL, > &netdev->tunnel_local); > + if (r < 0) { > + log_error_netdev(netdev, > + "Could not append IFLA_IPTUN_LOCAL > attribute: %s", > + strerror(-r)); > + return r; > + } > + > + r= sd_rtnl_message_append_in_addr(m, IFLA_IPTUN_REMOTE, > &netdev->tunnel_remote); > + if (r < 0) { > + log_error_netdev(netdev, > + "Could not append IFLA_IPTUN_REMOTE > attribute: %s", > + strerror(-r)); > + return r; > + } > + > + r = sd_rtnl_message_close_container(m); > + if (r < 0) { > + log_error_netdev(netdev, > + "Could not append IFLA_INFO_DATA attribute: > %s", > + strerror(-r)); > + return r; > + } > + > + r = sd_rtnl_message_close_container(m); > + if (r < 0) { > + log_error_netdev(netdev, > + "Could not append IFLA_LINKINFO attribute: > %s", > + strerror(-r)); > + return r; > + } > + > + r = sd_rtnl_call_async(netdev->manager->rtnl, m, > &netdev_create_handler, netdev, 0, NULL); > + if (r < 0) { > + log_error_netdev(netdev, > + "Could not send rtnetlink message: %s", > strerror(-r)); > + return r; > + } > + > + log_debug_netdev(netdev, "creating netdev tunnel"); Maybe also type of tunnel, netdev_kind_to_string(netdev->kind). > + > + netdev->state = NETDEV_STATE_CREATING; > + > + return 0; > +} > + > static int netdev_create(NetDev *netdev, Link *link, > sd_rtnl_message_handler_t callback) { > _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL; > const char *kind; > @@ -359,6 +521,11 @@ int netdev_enslave(NetDev *netdev, Link *link, > sd_rtnl_message_handler_t callbac > if (netdev->kind == NETDEV_KIND_VLAN || netdev->kind == > NETDEV_KIND_MACVLAN) > return netdev_create(netdev, link, callback); > > + if(netdev->kind == NETDEV_KIND_IPIP || > + netdev->kind == NETDEV_KIND_GRE || > + netdev->kind == NETDEV_KIND_SIT) > + return netdev_create_tunnel(link); > + > if (netdev->state == NETDEV_STATE_READY) { > netdev_enslave_ready(netdev, link, callback); > } else { > @@ -474,7 +641,7 @@ static int netdev_load_one(Manager *manager, const char > *filename) { > netdev->macvlan_mode = _NETDEV_MACVLAN_MODE_INVALID; > netdev->vlanid = VLANID_MAX + 1; > > - r = config_parse(NULL, filename, file, > "Match\0NetDev\0VLAN\0MACVLAN\0", > + r = config_parse(NULL, filename, file, > "Match\0NetDev\0VLAN\0MACVLAN\0Tunnel\0", > config_item_perf_lookup, (void*) > network_netdev_gperf_lookup, > false, false, netdev); > if (r < 0) { > diff --git a/src/network/networkd-network-gperf.gperf > b/src/network/networkd-network-gperf.gperf > index 6ba890f..bbc0f78 100644 > --- a/src/network/networkd-network-gperf.gperf > +++ b/src/network/networkd-network-gperf.gperf > @@ -34,6 +34,7 @@ Network.IPv4LL, config_parse_bool, > 0, > Network.Address, config_parse_address, 0, > 0 > Network.Gateway, config_parse_gateway, 0, > 0 > Network.DNS, config_parse_dns, 0, > offsetof(Network, dns) > +Network.Tunnel, config_parse_tunnel, 0, > offsetof(Network, tunnel) > Address.Address, config_parse_address, 0, > 0 > Address.Broadcast, config_parse_broadcast, 0, > 0 > Address.Label, config_parse_label, 0, > 0 > diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c > index bdf71e8..4f91eb8 100644 > --- a/src/network/networkd-network.c > +++ b/src/network/networkd-network.c > @@ -387,3 +387,40 @@ int config_parse_macvlan(const char *unit, > > return 0; > } > + > +int config_parse_tunnel(const char *unit, > + const char *filename, > + unsigned line, > + const char *section, > + unsigned section_line, > + const char *lvalue, > + int ltype, > + const char *rvalue, > + void *data, > + void *userdata) { > + Network *network = userdata; > + NetDev *netdev; > + int r; > + > + assert(filename); > + assert(lvalue); > + assert(rvalue); > + assert(data); > + > + r = netdev_get(network->manager, rvalue, &netdev); > + if (r < 0) { > + log_syntax(unit, LOG_ERR, filename, line, EINVAL, > + "Tunnel is invalid, ignoring assignment: %s", > rvalue); > + return 0; > + } > + > + if (netdev->kind != NETDEV_KIND_IPIP) { > + log_syntax(unit, LOG_ERR, filename, line, EINVAL, > + "NetDev is not a tunnel, ignoring assignment: > %s", rvalue); > + return 0; > + } > + > + network->tunnel = netdev; > + > + return 0; > +} > diff --git a/src/network/networkd.c b/src/network/networkd.c > index f0e6ad5..96c2217 100644 > --- a/src/network/networkd.c > +++ b/src/network/networkd.c > @@ -87,6 +87,12 @@ int main(int argc, char *argv[]) { > goto out; > } > > + r = manager_init_kmod_ctx(m); > + if (r < 0) { > + log_error("Could not init kmod context: %s", strerror(-r)); > + goto out; > + } > + > r = manager_udev_enumerate_links(m); > if (r < 0) { > log_error("Could not enumerate links: %s", strerror(-r)); > diff --git a/src/network/networkd.h b/src/network/networkd.h > index 36902e3..c281985 100644 > --- a/src/network/networkd.h > +++ b/src/network/networkd.h > @@ -68,6 +68,9 @@ typedef enum NetDevKind { > NETDEV_KIND_BOND, > NETDEV_KIND_VLAN, > NETDEV_KIND_MACVLAN, > + NETDEV_KIND_IPIP, > + NETDEV_KIND_GRE, > + NETDEV_KIND_SIT, > _NETDEV_KIND_MAX, > _NETDEV_KIND_INVALID = -1 > } NetDevKind; > @@ -100,6 +103,11 @@ struct NetDev { > int ifindex; > NetDevState state; > > + unsigned tunnel_ttl; > + unsigned tunnel_mtu; > + struct in_addr tunnel_local; > + struct in_addr tunnel_remote; > + > LIST_HEAD(netdev_enslave_callback, callbacks); > }; > > @@ -121,6 +129,7 @@ struct Network { > char *description; > NetDev *bridge; > NetDev *bond; > + NetDev *tunnel; > Hashmap *vlans; > Hashmap *macvlans; > bool dhcp; > @@ -234,6 +243,7 @@ struct Manager { > LIST_HEAD(Network, networks); > > usec_t network_dirs_ts_usec; > + struct kmod_ctx *kmod_ctx; > }; > > extern const char* const network_dirs[]; > @@ -253,6 +263,7 @@ int manager_rtnl_listen(Manager *m); > int manager_bus_listen(Manager *m); > > int manager_update_resolv_conf(Manager *m); > +int manager_init_kmod_ctx(Manager *m); > > DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free); > #define _cleanup_manager_free_ _cleanup_(manager_freep) > @@ -269,6 +280,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(NetDev*, netdev_free); > int netdev_get(Manager *manager, const char *name, NetDev **ret); > int netdev_set_ifindex(NetDev *netdev, sd_rtnl_message *newlink); > int netdev_enslave(NetDev *netdev, Link *link, sd_rtnl_message_handler_t cb); > +int netdev_create_tunnel(Link *link); > > const char *netdev_kind_to_string(NetDevKind d) _const_; > NetDevKind netdev_kind_from_string(const char *d) _pure_; > @@ -311,6 +323,21 @@ int config_parse_macvlan(const char *unit, const char > *filename, unsigned line, > const char *section, unsigned section_line, const > char *lvalue, > int ltype, const char *rvalue, void *data, void > *userdata); > > +int config_parse_tunnel(const char *unit, const char *filename, unsigned > line, > + const char *section, unsigned section_line, const > char *lvalue, > + int ltype, const char *rvalue, void *data, void > *userdata); > + > +int config_parse_tunnel_address(const char *unit, > + const char *filename, > + unsigned line, > + const char *section, > + unsigned section_line, > + const char *lvalue, > + int ltype, > + const char *rvalue, > + void *data, > + void *userdata); > + > /* gperf */ > const struct ConfigPerfItem* network_network_gperf_lookup(const char *key, > unsigned length); > > -- > 1.9.0 > > _______________________________________________ > systemd-devel mailing list > systemd-devel@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/systemd-devel _______________________________________________ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel