-#ifdef GRE_IOCTL_ONLY
- return EOPNOTSUPP;
-#else
- int error;
- struct ofpbuf request, *reply;
- unsigned int nl_flags;
- struct ifinfomsg ifinfomsg;
- struct nlattr *linkinfo_hdr;
- struct nlattr *info_data_hdr;
- uint16_t iflags = 0;
- uint16_t oflags = 0;
- uint8_t pmtudisc = 0;
-
- if (!gre_descriptors.nl_sock) {
- error = nl_sock_create(NETLINK_ROUTE, 0, 0, 0,
- &gre_descriptors.nl_sock);
- if (error) {
- VLOG_WARN("couldn't create netlink socket: %s\n", strerror(error));
- gre_descriptors.nl_sock = NULL;
- goto error;
- }
- }
-
- ofpbuf_init(&request, 0);
-
- nl_flags = NLM_F_REQUEST;
- if (create) {
- nl_flags |= NLM_F_CREATE|NLM_F_EXCL;
- }
-
- /* We over-reserve space, because we do some pointer arithmetic
- * and don't want the buffer address shifting under us. */
- nl_msg_put_nlmsghdr(&request, gre_descriptors.nl_sock, 2048, RTM_NEWLINK,
- nl_flags);
-
- memset(&ifinfomsg, 0, sizeof ifinfomsg);
- ifinfomsg.ifi_family = AF_UNSPEC;
- nl_msg_put(&request, &ifinfomsg, sizeof ifinfomsg);
-
- linkinfo_hdr = ofpbuf_tail(&request);
- nl_msg_put_unspec(&request, IFLA_LINKINFO, NULL, 0);
-
- nl_msg_put_unspec(&request, IFLA_INFO_KIND, "gretap", 6);
-
- info_data_hdr = ofpbuf_tail(&request);
- nl_msg_put_unspec(&request, IFLA_INFO_DATA, NULL, 0);
-
- /* Set flags */
- if (config->have_in_key) {
- iflags |= GRE_KEY;
- }
- if (config->have_out_key) {
- oflags |= GRE_KEY;
- }
-
- if (config->in_csum) {
- iflags |= GRE_CSUM;
- }
- if (config->out_csum) {
- oflags |= GRE_CSUM;
- }
-
- /* Add options */
- nl_msg_put_u32(&request, IFLA_GRE_IKEY, config->in_key);
- nl_msg_put_u32(&request, IFLA_GRE_OKEY, config->out_key);
- nl_msg_put_u16(&request, IFLA_GRE_IFLAGS, iflags);
- nl_msg_put_u16(&request, IFLA_GRE_OFLAGS, oflags);
- nl_msg_put_u32(&request, IFLA_GRE_LOCAL, config->local_ip);
- nl_msg_put_u32(&request, IFLA_GRE_REMOTE, config->remote_ip);
- nl_msg_put_u8(&request, IFLA_GRE_PMTUDISC, pmtudisc);
- nl_msg_put_u8(&request, IFLA_GRE_TTL, 0);
- nl_msg_put_u8(&request, IFLA_GRE_TOS, 0);
-
- info_data_hdr->nla_len = (char *)ofpbuf_tail(&request)
- - (char *)info_data_hdr;
- linkinfo_hdr->nla_len = (char *)ofpbuf_tail(&request)
- - (char *)linkinfo_hdr;