From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.8 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 56FD1C10F0E for ; Tue, 9 Apr 2019 19:14:47 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 145BB2084F for ; Tue, 9 Apr 2019 19:14:47 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="pASv9qqW" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726805AbfDITOp (ORCPT ); Tue, 9 Apr 2019 15:14:45 -0400 Received: from mail-wm1-f65.google.com ([209.85.128.65]:50236 "EHLO mail-wm1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726663AbfDITOo (ORCPT ); Tue, 9 Apr 2019 15:14:44 -0400 Received: by mail-wm1-f65.google.com with SMTP id z11so4914707wmi.0 for ; Tue, 09 Apr 2019 12:14:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=uO4hyyr/6FcsdURZqU99AxTxJxmJK8C176rFAhaxjR8=; b=pASv9qqWZ3/1etqpJKY/KWcxRGR++8WZjpvppxKsMxvOU/B5tzDsgwyG5Urp2FnE1w rqIJf1M5+1yZralsj3efbm+fg6n1Yeya+ptTMO2+/U4H1FCFrwZ8duOkcPvfX62yRuy1 KKuv0cEUYUNLEVZZey4qaiO6lpZXLLok6eused5jwSekrV5o+LbZA7OjyCgsCHwT1qde 29Tm0meLT4Qj6l2j7ekljZyXLty/UZK0zOoAJoZ+oKRJz4j3FDlzY1wEAhf0nqoFjMdG b1cnA1UIG9Z0AIcAaH7wBrKKelU1sUDfTwg9gKvZC9U4TkKmP5oxDzpPB8Kp8Jfb4ZGj A3dg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=uO4hyyr/6FcsdURZqU99AxTxJxmJK8C176rFAhaxjR8=; b=GXIgPTX6LaYwZ5WdpVABen+5ijErMA/k2jMiciVPhh1VGcvpDIpPJABsHGb3iMT0D2 JcO+DtDt1+p2BX7J1ltk6HjVY9QoDAPKfFgtFdxQnQjCObXtSwvPCBndEZb4+Qa8W619 vm0lcTDR6KyHkqfJ9SLc7henMQbJhaycrZS4uYONeTbq2OM7LYeeFS+vK84NQJcbNgpc PSWqOepkZ0TIcUGUGUWX2URDwjuIZj+rCoZYQh9MJyFIvYMrfTrcq29OWnUXxtoa0AXG cgRdIVRBdHvZbsOxzA+hiAH+GnKSb7IPMK8fUqVg+8AmVpHlc+AyRpTqopn9A3k5t/Kl ZkLQ== X-Gm-Message-State: APjAAAX5Hyy0DP9oyoy5v0g4wm+9LY+oZTmbbnSsxPWOcrCH1vSTS+gk UcKg8zd2C+9k65Jhl8FjbenaDgPw X-Google-Smtp-Source: APXvYqwMHrRck+vf7HheYSR3GMgb0ilVFaK688l4YeW6j0w8+jVAQnWwjTO3WX9McD0INrIwRqLhQw== X-Received: by 2002:a1c:1a53:: with SMTP id a80mr22777935wma.15.1554837282050; Tue, 09 Apr 2019 12:14:42 -0700 (PDT) Received: from kristrev-XPS-15-9570.lan ([193.213.155.210]) by smtp.gmail.com with ESMTPSA id f15sm41109657wru.21.2019.04.09.12.14.41 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 09 Apr 2019 12:14:41 -0700 (PDT) From: Kristian Evensen To: netdev@vger.kernel.org Cc: Kristian Evensen Subject: [PATCH iproute2-next] ip fou: Support binding FOU ports Date: Tue, 9 Apr 2019 21:14:37 +0200 Message-Id: <20190409191437.24135-1-kristian.evensen@gmail.com> X-Mailer: git-send-email 2.19.1 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org This patch adds support for binding FOU ports using iproute2. Kernel-support was added in 1713cb37bf67 ("fou: Support binding FoU socket"). The parse function now handles new arguments for setting the binding-related attributes, while the print function writes the new attributes if they are set. Also, the man page has been updated. Signed-off-by: Kristian Evensen --- include/uapi/linux/fou.h | 6 +++ ip/ipfou.c | 106 +++++++++++++++++++++++++++++++++++++-- man/man8/ip-fou.8 | 49 +++++++++++++++++- 3 files changed, 155 insertions(+), 6 deletions(-) diff --git a/include/uapi/linux/fou.h b/include/uapi/linux/fou.h index bf022c63..9f915118 100644 --- a/include/uapi/linux/fou.h +++ b/include/uapi/linux/fou.h @@ -16,6 +16,12 @@ enum { FOU_ATTR_IPPROTO, /* u8 */ FOU_ATTR_TYPE, /* u8 */ FOU_ATTR_REMCSUM_NOPARTIAL, /* flag */ + FOU_ATTR_LOCAL_V4, /* u32 */ + FOU_ATTR_LOCAL_V6, /* in6_addr */ + FOU_ATTR_PEER_V4, /* u32 */ + FOU_ATTR_PEER_V6, /* in6_addr */ + FOU_ATTR_PEER_PORT, /* u16 */ + FOU_ATTR_IFINDEX, /* s32 */ __FOU_ATTR_MAX, }; diff --git a/ip/ipfou.c b/ip/ipfou.c index 346522dd..8bc62d78 100644 --- a/ip/ipfou.c +++ b/ip/ipfou.c @@ -28,11 +28,17 @@ static void usage(void) { fprintf(stderr, "Usage: ip fou add port PORT { ipproto PROTO | gue } [ -6 ]\n" - " ip fou del port PORT [ -6 ]\n" + " [ local IFADDR ] [ peer IFADDR ]\n" + " [ peer_port PORT ] [ index IDX ]\n" + " ip fou del port PORT [ -6 ] [ local IFADDR ]\n" + " [ peer IFADDR ] [ peer_port PORT ]\n" + " [ index IDX ]\n" " ip fou show\n" "\n" "Where: PROTO { ipproto-name | 1..255 }\n" - " PORT { 1..65535 }\n"); + " PORT { 1..65535 }\n" + " IFADDR { addr }\n" + " IDX { interface index }\n"); exit(-1); } @@ -48,12 +54,14 @@ static int genl_family = -1; static int fou_parse_opt(int argc, char **argv, struct nlmsghdr *n, bool adding) { - __u16 port; - int port_set = 0; + __u16 port, peer_port; + int port_set = 0, peer_port_set = 0; __u8 ipproto, type; bool gue_set = false; int ipproto_set = 0; __u8 family = AF_INET; + const char *local = NULL, *peer = NULL; + int index, index_set = 0; while (argc > 0) { if (!matches(*argv, "port")) { @@ -77,6 +85,26 @@ static int fou_parse_opt(int argc, char **argv, struct nlmsghdr *n, gue_set = true; } else if (!matches(*argv, "-6")) { family = AF_INET6; + } else if (!matches(*argv, "local")) { + NEXT_ARG(); + + local = *argv; + } else if (!matches(*argv, "peer")) { + NEXT_ARG(); + + peer = *argv; + } else if (!matches(*argv, "peer_port")) { + NEXT_ARG(); + + if (get_be16(&peer_port, *argv, 0) || peer_port == 0) + invarg("invalid peer port", *argv); + peer_port_set = 1; + } else if (!matches(*argv, "index")) { + NEXT_ARG(); + + if (get_s32(&index, *argv, 0) || index == 0) + invarg("invalid interface index", *argv); + index_set = 1; } else { fprintf(stderr , "fou: unknown command \"%s\"?\n", *argv); @@ -101,6 +129,11 @@ static int fou_parse_opt(int argc, char **argv, struct nlmsghdr *n, return -1; } + if ((peer_port_set && !peer) || (peer && !peer_port_set)) { + fprintf(stderr, "fou: both peer and peer port must be set\n"); + return -1; + } + type = gue_set ? FOU_ENCAP_GUE : FOU_ENCAP_DIRECT; addattr16(n, 1024, FOU_ATTR_PORT, port); @@ -110,6 +143,32 @@ static int fou_parse_opt(int argc, char **argv, struct nlmsghdr *n, if (ipproto_set) addattr8(n, 1024, FOU_ATTR_IPPROTO, ipproto); + if (local) { + inet_prefix local_addr; + __u8 attr_type = family == AF_INET ? FOU_ATTR_LOCAL_V4 : + FOU_ATTR_LOCAL_V6; + + get_addr(&local_addr, local, family); + addattr_l(n, 1024, attr_type, &local_addr.data, + local_addr.bytelen); + } + + if (peer) { + inet_prefix peer_addr; + __u8 attr_type = family == AF_INET ? FOU_ATTR_PEER_V4 : + FOU_ATTR_PEER_V6; + + get_addr(&peer_addr, peer, family); + addattr_l(n, 1024, attr_type, &peer_addr.data, + peer_addr.bytelen); + + if (peer_port_set) + addattr16(n, 1024, FOU_ATTR_PEER_PORT, peer_port); + } + + if (index_set) + addattr32(n, 1024, FOU_ATTR_IFINDEX, index); + return 0; } @@ -142,6 +201,8 @@ static int print_fou_mapping(struct nlmsghdr *n, void *arg) struct genlmsghdr *ghdr; struct rtattr *tb[FOU_ATTR_MAX + 1]; int len = n->nlmsg_len; + __u8 family = AF_INET, local_attr_type, peer_attr_type, byte_len; + __u8 empty_buf[16] = {0}; if (n->nlmsg_type != genl_family) return 0; @@ -166,7 +227,7 @@ static int print_fou_mapping(struct nlmsghdr *n, void *arg) " ipproto %u", rta_getattr_u8(tb[FOU_ATTR_IPPROTO])); if (tb[FOU_ATTR_AF]) { - __u8 family = rta_getattr_u8(tb[FOU_ATTR_AF]); + family = rta_getattr_u8(tb[FOU_ATTR_AF]); print_string(PRINT_JSON, "family", NULL, family_name(family)); @@ -175,6 +236,41 @@ static int print_fou_mapping(struct nlmsghdr *n, void *arg) print_string(PRINT_FP, NULL, " -6", NULL); } + + local_attr_type = family == AF_INET ? FOU_ATTR_LOCAL_V4 : + FOU_ATTR_LOCAL_V6; + peer_attr_type = family == AF_INET ? FOU_ATTR_PEER_V4 : + FOU_ATTR_PEER_V6; + byte_len = af_bit_len(family) / 8; + + if (tb[local_attr_type] && memcmp(RTA_DATA(tb[local_attr_type]), + empty_buf, byte_len)) { + print_string(PRINT_ANY, "local", " local %s", + format_host_rta(family, tb[local_attr_type])); + } + + if (tb[peer_attr_type] && memcmp(RTA_DATA(tb[peer_attr_type]), + empty_buf, byte_len)) { + print_string(PRINT_ANY, "peer", " peer %s", + format_host_rta(family, tb[peer_attr_type])); + } + + if (tb[FOU_ATTR_PEER_PORT]) { + __u16 p_port = ntohs(rta_getattr_u16(tb[FOU_ATTR_PEER_PORT])); + + if (p_port) + print_uint(PRINT_ANY, "peer_port", " peer_port %u", + p_port); + + } + + if (tb[FOU_ATTR_IFINDEX]) { + int index = rta_getattr_s32(tb[FOU_ATTR_IFINDEX]); + + if (index) + print_int(PRINT_ANY, "index", " index %d", index); + } + print_string(PRINT_FP, NULL, "\n", NULL); close_json_object(); diff --git a/man/man8/ip-fou.8 b/man/man8/ip-fou.8 index 81cab928..2f51c156 100644 --- a/man/man8/ip-fou.8 +++ b/man/man8/ip-fou.8 @@ -24,11 +24,43 @@ ip-gue \- Generic UDP Encapsulation receive port configuration .B ipproto .IR PROTO .RB " }" +.RB "[ " +.B local +.IR IFADDR +.RB " ]" +.RB "[ " +.B peer +.IR IFADDR +.RB " ]" +.RB "[ " +.B peer_port +.IR PORT +.RB " ]" +.RB "[ " +.B index +.IR IDX +.RB " ]" .br .ti -8 .BR "ip fou del" .B port .IR PORT +.RB "[ " +.B local +.IR IFADDR +.RB " ]" +.RB "[ " +.B peer +.IR IFADDR +.RB " ]" +.RB "[ " +.B peer_port +.IR PORT +.RB " ]" +.RB "[ " +.B index +.IR IDX +.RB " ]" .br .ti -8 .B ip fou show @@ -50,11 +82,22 @@ When creating a FOU or GUE receive port, the port number is specified in .I PORT argument. If FOU is used, the IP protocol number associated with the port is specified in .I PROTO +argument. You can bind a port to a local address/interface, by specifying the +address in the local +.I IFADDR +argument or interface index in the +.I IDX +argument. If you would like to connect the port, you can specify the peer +address in the peer +.I IFADDR +argument and peer port in the peer_port +.I PORT argument. .PP A FOU or GUE receive port is deleted by specifying .I PORT -in the delete command. +in the delete command, as well as local address/interface or peer address/port +(if set). .SH EXAMPLES .PP .SS Configure a FOU receive port for GRE bound to 7777 @@ -72,6 +115,10 @@ in the delete command. .SS Delete the GUE receive port bound to 9999 .nf # ip fou del port 9999 +.SS Configure a FOU receive port for GRE bound to 1.2.3.4:7777 +.nf +# ip fou add port 7777 ipproto 47 local 1.2.3.4 +.PP .SH SEE ALSO .br .BR ip (8) -- 2.19.1