diff --git a/criu/net.c b/criu/net.c index d3aec78a95..d760d01953 100644 --- a/criu/net.c +++ b/criu/net.c @@ -55,6 +55,30 @@ #define IFLA_MACVLAN_FLAGS 2 #endif +enum { + IFLA_IPTUN_UNSPEC, + IFLA_IPTUN_LINK, + IFLA_IPTUN_LOCAL, + IFLA_IPTUN_REMOTE, + IFLA_IPTUN_TTL, + IFLA_IPTUN_TOS, + IFLA_IPTUN_ENCAP_LIMIT, + IFLA_IPTUN_FLOWINFO, + IFLA_IPTUN_FLAGS, + IFLA_IPTUN_PROTO, + IFLA_IPTUN_PMTUDISC, + IFLA_IPTUN_6RD_PREFIX, + IFLA_IPTUN_6RD_RELAY_PREFIX, + IFLA_IPTUN_6RD_PREFIXLEN, + IFLA_IPTUN_6RD_RELAY_PREFIXLEN, + IFLA_IPTUN_ENCAP_TYPE, + IFLA_IPTUN_ENCAP_FLAGS, + IFLA_IPTUN_ENCAP_SPORT, + IFLA_IPTUN_ENCAP_DPORT, + __IFLA_IPTUN_MAX, +}; +#define IFLA_IPTUN_MAX (__IFLA_IPTUN_MAX - 1) + static int ns_sysfs_fd = -1; int read_ns_sys_file(char *path, char *buf, int len) @@ -658,8 +682,108 @@ static int dump_one_gre(struct ifinfomsg *ifi, char *kind, return dump_unknown_device(ifi, kind, tb, ns, fds); } +static int dump_sit(NetDeviceEntry *nde, struct cr_imgset *imgset, struct nlattr **info) +{ + int ret; + struct nlattr *data[__IFLA_IPTUN_MAX]; + SitEntry se = SIT_ENTRY__INIT; + /* There are for IP(v6) addresses kernel feeds to us */ + uint32_t a_local, a_remote, rd_prefix[4], rl_prefix; + + if (!info || !info[IFLA_INFO_DATA]) { + pr_err("no data for sit\n"); + return -1; + } + + pr_info("Some data for SIT provided\n"); + ret = nla_parse_nested(data, IFLA_IPTUN_MAX, info[IFLA_INFO_DATA], NULL); + if (ret < 0) { + pr_err("failed ot parse sit data\n"); + return -1; + } + +#define ENCODE_ENTRY(__type, __ifla, __proto) do { \ + if (data[__ifla]) { \ + se.__proto = *(__type *)nla_data(data[__ifla]); \ + if (se.__proto) \ + se.has_##__proto = true; \ + } \ + } while (0) + + if (data[IFLA_IPTUN_LOCAL]) { + a_local = *(u32 *)nla_data(data[IFLA_IPTUN_LOCAL]); + if (a_local != 0) { + se.n_local = 1; + se.local = &a_local; + } + } + + if (data[IFLA_IPTUN_REMOTE]) { + a_remote = *(u32 *)nla_data(data[IFLA_IPTUN_REMOTE]); + if (a_remote != 0) { + se.n_remote = 1; + se.remote = &a_remote; + } + } + + ENCODE_ENTRY(u32, IFLA_IPTUN_LINK, link); + ENCODE_ENTRY(u8, IFLA_IPTUN_TTL, ttl); + ENCODE_ENTRY(u8, IFLA_IPTUN_TOS, tos); + ENCODE_ENTRY(u16, IFLA_IPTUN_FLAGS, flags); + ENCODE_ENTRY(u8, IFLA_IPTUN_PROTO, proto); + + if (data[IFLA_IPTUN_PMTUDISC]) { + u8 v; + + v = *(u8 *)nla_data(data[IFLA_IPTUN_PMTUDISC]); + if (v) + se.pmtudisc = se.has_pmtudisc = true; + } + + ENCODE_ENTRY(u16, IFLA_IPTUN_ENCAP_TYPE, encap_type); + ENCODE_ENTRY(u16, IFLA_IPTUN_ENCAP_FLAGS, encap_flags); + ENCODE_ENTRY(u16, IFLA_IPTUN_ENCAP_SPORT, encap_sport); + ENCODE_ENTRY(u16, IFLA_IPTUN_ENCAP_DPORT, encap_dport); + + if (data[IFLA_IPTUN_6RD_PREFIXLEN]) { + se.rd_prefixlen = *(u16 *)nla_data(data[IFLA_IPTUN_6RD_PREFIXLEN]); + if (!se.rd_prefixlen) + goto skip; + + if (!data[IFLA_IPTUN_6RD_PREFIX]) { + pr_err("No 6rd prefix for sit device\n"); + return -1; + } + + se.has_rd_prefixlen = true; + memcpy(&rd_prefix, nla_data(data[IFLA_IPTUN_6RD_PREFIX]), sizeof(rd_prefix)); + se.n_rd_prefix = 4; + se.rd_prefix = rd_prefix; + + se.relay_prefixlen = *(u16 *)nla_data(data[IFLA_IPTUN_6RD_RELAY_PREFIXLEN]); + if (!se.relay_prefixlen) + goto skip; + + if (!data[IFLA_IPTUN_6RD_RELAY_PREFIX]) { + pr_err("No 6rd relay prefix for sit device\n"); + return -1; + } + + se.has_relay_prefixlen = true; + memcpy(&rl_prefix, nla_data(data[IFLA_IPTUN_6RD_RELAY_PREFIX]), sizeof(rl_prefix)); + se.n_relay_prefix = 1; + se.relay_prefix = &rl_prefix; +skip:; + } + +#undef ENCODE_ENTRY + + nde->sit = &se; + return write_netdev_img(nde, imgset, info); +} + static int dump_one_sit(struct ifinfomsg *ifi, char *kind, - struct nlattr **tb, struct cr_imgset *fds) + struct nlattr **tb, struct ns_id *ns, struct cr_imgset *fds) { char *name; @@ -679,8 +803,7 @@ static int dump_one_sit(struct ifinfomsg *ifi, char *kind, return 0; } - pr_warn("SIT device %s not supported natively\n", name); - return dump_unknown_device(ifi, kind, tb, fds); + return dump_one_netdev(ND_TYPE__SIT, ifi, tb, ns, fds, dump_sit); } static int list_one_link(struct nlmsghdr *hdr, struct ns_id *ns, void *arg) @@ -727,7 +850,7 @@ static int dump_one_link(struct nlmsghdr *hdr, struct ns_id *ns, void *arg) ret = dump_one_gre(ifi, kind, tb, ns, fds); break; case ARPHRD_SIT: - ret = dump_one_sit(ifi, kind, tb, fds); + ret = dump_one_sit(ifi, kind, tb, ns, fds); break; default: unk: diff --git a/images/Makefile b/images/Makefile index af226dc31c..f1af8372b8 100644 --- a/images/Makefile +++ b/images/Makefile @@ -61,6 +61,7 @@ proto-obj-y += time.o proto-obj-y += sysctl.o proto-obj-y += autofs.o proto-obj-y += macvlan.o +proto-obj-y += sit.o proto-obj-y += remote-image.o CFLAGS += -iquote $(obj)/ diff --git a/images/netdev.proto b/images/netdev.proto index 564dd43e8c..0cd116e300 100644 --- a/images/netdev.proto +++ b/images/netdev.proto @@ -4,6 +4,7 @@ import "macvlan.proto"; import "opts.proto"; import "tun.proto"; import "sysctl.proto"; +import "sit.proto"; enum nd_type { LOOPBACK = 1; @@ -19,6 +20,7 @@ enum nd_type { VENET = 5; /* OpenVZ device */ BRIDGE = 6; MACVLAN = 7; + SIT = 8; } message net_device_entry { @@ -44,6 +46,7 @@ message net_device_entry { optional uint32 peer_nsid = 13; optional uint32 master = 14; + optional sit_entry sit = 15; } message netns_id { diff --git a/images/sit.proto b/images/sit.proto new file mode 100644 index 0000000000..7ca91ccd0e --- /dev/null +++ b/images/sit.proto @@ -0,0 +1,22 @@ +syntax = "proto2"; + +import "opts.proto"; + +message sit_entry { + optional uint32 link = 1; + repeated uint32 local = 2 [(criu).ipadd = true]; + repeated uint32 remote = 3 [(criu).ipadd = true]; + optional uint32 ttl = 4; + optional uint32 tos = 5; + optional bool pmtudisc = 6; + optional uint32 proto = 7; + optional uint32 flags = 8; + optional uint32 encap_type = 9; + optional uint32 encap_flags = 10; + optional uint32 encap_sport = 11; + optional uint32 encap_dport = 12; + optional uint32 rd_prefixlen = 13; + repeated uint32 rd_prefix = 14 [(criu).ipadd = true]; + optional uint32 relay_prefixlen = 15; + repeated uint32 relay_prefix = 16 [(criu).ipadd = true]; +};