ip: add AMT support

Add basic support for Automatic Multicast Tunneling (AMT) network devices.

Signed-off-by: Taehee Yoo <ap420073@gmail.com>
This commit is contained in:
Taehee Yoo 2021-10-30 14:08:58 +00:00 committed by David Ahern
parent 9cae1de564
commit 6e15d27aae
5 changed files with 251 additions and 4 deletions

View File

@ -11,7 +11,8 @@ IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o ipnetns.o \
iplink_bridge.o iplink_bridge_slave.o ipfou.o iplink_ipvlan.o \ iplink_bridge.o iplink_bridge_slave.o ipfou.o iplink_ipvlan.o \
iplink_geneve.o iplink_vrf.o iproute_lwtunnel.o ipmacsec.o ipila.o \ iplink_geneve.o iplink_vrf.o iproute_lwtunnel.o ipmacsec.o ipila.o \
ipvrf.o iplink_xstats.o ipseg6.o iplink_netdevsim.o iplink_rmnet.o \ ipvrf.o iplink_xstats.o ipseg6.o iplink_netdevsim.o iplink_rmnet.o \
ipnexthop.o ipmptcp.o iplink_bareudp.o iplink_wwan.o ipioam6.o ipnexthop.o ipmptcp.o iplink_bareudp.o iplink_wwan.o ipioam6.o \
iplink_amt.o
RTMONOBJ=rtmon.o RTMONOBJ=rtmon.o

View File

@ -64,8 +64,8 @@ static void usage(void)
fprintf(stderr, fprintf(stderr,
"Usage: ip [ OPTIONS ] OBJECT { COMMAND | help }\n" "Usage: ip [ OPTIONS ] OBJECT { COMMAND | help }\n"
" ip [ -force ] -batch filename\n" " ip [ -force ] -batch filename\n"
"where OBJECT := { address | addrlabel | fou | help | ila | ioam | l2tp | link |\n" "where OBJECT := { address | addrlabel | amt | fou | help | ila | ioam | l2tp |\n"
" macsec | maddress | monitor | mptcp | mroute | mrule |\n" " link | macsec | maddress | monitor | mptcp | mroute | mrule |\n"
" neighbor | neighbour | netconf | netns | nexthop | ntable |\n" " neighbor | neighbour | netconf | netns | nexthop | ntable |\n"
" ntbl | route | rule | sr | tap | tcpmetrics |\n" " ntbl | route | rule | sr | tap | tcpmetrics |\n"
" token | tunnel | tuntap | vrf | xfrm }\n" " token | tunnel | tuntap | vrf | xfrm }\n"

View File

@ -50,7 +50,7 @@ void iplink_types_usage(void)
{ {
/* Remember to add new entry here if new type is added. */ /* Remember to add new entry here if new type is added. */
fprintf(stderr, fprintf(stderr,
"TYPE := { bareudp | bond | bond_slave | bridge | bridge_slave |\n" "TYPE := { amt | bareudp | bond | bond_slave | bridge | bridge_slave |\n"
" dummy | erspan | geneve | gre | gretap | ifb |\n" " dummy | erspan | geneve | gre | gretap | ifb |\n"
" ip6erspan | ip6gre | ip6gretap | ip6tnl |\n" " ip6erspan | ip6gre | ip6gretap | ip6tnl |\n"
" ipip | ipoib | ipvlan | ipvtap |\n" " ipip | ipoib | ipvlan | ipvtap |\n"

200
ip/iplink_amt.c Normal file
View File

@ -0,0 +1,200 @@
/*
* iplink_amt.c AMT device support
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
* Authors: Taehee Yoo <ap420073@gmail.com>
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <net/if.h>
#include <linux/ip.h>
#include <linux/if_link.h>
#include <arpa/inet.h>
#include <linux/amt.h>
#include "rt_names.h"
#include "utils.h"
#include "ip_common.h"
#define AMT_ATTRSET(attrs, type) (((attrs) & (1L << (type))) != 0)
static void print_usage(FILE *f)
{
fprintf(f,
"Usage: ... amt\n"
" [ discovery IP_ADDRESS ]\n"
" [ mode MODE ]\n"
" [ local ADDR ]\n"
" [ dev PHYS_DEV ]\n"
" [ relay_port PORT ]\n"
" [ gateway_port PORT ]\n"
" [ max_tunnels NUMBER ]\n"
"\n"
"Where: ADDR := { IP_ADDRESS }\n"
" MODE := { gateway | relay }\n"
);
}
static char *modename[] = {"gateway", "relay"};
static void usage(void)
{
print_usage(stderr);
}
static void check_duparg(__u64 *attrs, int type, const char *key,
const char *argv)
{
if (!AMT_ATTRSET(*attrs, type)) {
*attrs |= (1L << type);
return;
}
duparg2(key, argv);
}
static int amt_parse_opt(struct link_util *lu, int argc, char **argv,
struct nlmsghdr *n)
{
unsigned int mode, max_tunnels;
inet_prefix saddr, daddr;
__u64 attrs = 0;
__u16 port;
saddr.family = daddr.family = AF_UNSPEC;
inet_prefix_reset(&saddr);
inet_prefix_reset(&daddr);
while (argc > 0) {
if (strcmp(*argv, "mode") == 0) {
NEXT_ARG();
if (strcmp(*argv, "gateway") == 0) {
mode = 0;
} else if (strcmp(*argv, "relay") == 0) {
mode = 1;
} else {
usage();
return -1;
}
addattr32(n, 1024, IFLA_AMT_MODE, mode);
} else if (strcmp(*argv, "relay_port") == 0) {
NEXT_ARG();
if (get_u16(&port, *argv, 0))
invarg("relay_port", *argv);
addattr16(n, 1024, IFLA_AMT_RELAY_PORT, htons(port));
} else if (strcmp(*argv, "gateway_port") == 0) {
NEXT_ARG();
if (get_u16(&port, *argv, 0))
invarg("gateway_port", *argv);
addattr16(n, 1024, IFLA_AMT_GATEWAY_PORT, htons(port));
} else if (strcmp(*argv, "max_tunnels") == 0) {
NEXT_ARG();
if (get_u32(&max_tunnels, *argv, 0))
invarg("max_tunnels", *argv);
addattr32(n, 1024, IFLA_AMT_MAX_TUNNELS, max_tunnels);
} else if (strcmp(*argv, "dev") == 0) {
unsigned int link;
NEXT_ARG();
link = ll_name_to_index(*argv);
if (!link)
exit(nodev(*argv));
addattr32(n, 1024, IFLA_AMT_LINK, link);
} else if (strcmp(*argv, "local") == 0) {
NEXT_ARG();
check_duparg(&attrs, IFLA_AMT_LOCAL_IP, "local", *argv);
get_addr(&saddr, *argv, daddr.family);
if (is_addrtype_inet(&saddr))
addattr_l(n, 1024, IFLA_AMT_LOCAL_IP,
saddr.data, saddr.bytelen);
} else if (strcmp(*argv, "discovery") == 0) {
NEXT_ARG();
check_duparg(&attrs, IFLA_AMT_DISCOVERY_IP,
"discovery", *argv);
get_addr(&daddr, *argv, daddr.family);
if (is_addrtype_inet(&daddr))
addattr_l(n, 1024, IFLA_AMT_DISCOVERY_IP,
daddr.data, daddr.bytelen);
} else if (strcmp(*argv, "help") == 0) {
usage();
return -1;
} else {
fprintf(stderr, "amt: unknown command \"%s\"?\n", *argv);
usage();
return -1;
}
argc--, argv++;
}
return 0;
}
static void amt_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
{
if (!tb)
return;
if (tb[IFLA_AMT_MODE])
print_string(PRINT_ANY, "mode", "%s ",
modename[rta_getattr_u32(tb[IFLA_AMT_MODE])]);
if (tb[IFLA_AMT_GATEWAY_PORT])
print_uint(PRINT_ANY, "gateway_port", "gateway_port %u ",
rta_getattr_be16(tb[IFLA_AMT_GATEWAY_PORT]));
if (tb[IFLA_AMT_RELAY_PORT])
print_uint(PRINT_ANY, "relay_port", "relay_port %u ",
rta_getattr_be16(tb[IFLA_AMT_RELAY_PORT]));
if (tb[IFLA_AMT_LOCAL_IP]) {
__be32 addr = rta_getattr_u32(tb[IFLA_AMT_LOCAL_IP]);
print_string(PRINT_ANY, "local", "local %s ",
format_host(AF_INET, 4, &addr));
}
if (tb[IFLA_AMT_REMOTE_IP]) {
__be32 addr = rta_getattr_u32(tb[IFLA_AMT_REMOTE_IP]);
print_string(PRINT_ANY, "remote", "remote %s ",
format_host(AF_INET, 4, &addr));
}
if (tb[IFLA_AMT_DISCOVERY_IP]) {
__be32 addr = rta_getattr_u32(tb[IFLA_AMT_DISCOVERY_IP]);
print_string(PRINT_ANY, "discovery", "discovery %s ",
format_host(AF_INET, 4, &addr));
}
if (tb[IFLA_AMT_LINK]) {
unsigned int link = rta_getattr_u32(tb[IFLA_AMT_LINK]);
print_string(PRINT_ANY, "link", "dev %s ",
ll_index_to_name(link));
}
if (tb[IFLA_AMT_MAX_TUNNELS])
print_uint(PRINT_ANY, "max_tunnels", "max_tunnels %u ",
rta_getattr_u32(tb[IFLA_AMT_MAX_TUNNELS]));
}
static void amt_print_help(struct link_util *lu, int argc, char **argv, FILE *f)
{
print_usage(f);
}
struct link_util amt_link_util = {
.id = "amt",
.maxattr = IFLA_AMT_MAX,
.parse_opt = amt_parse_opt,
.print_opt = amt_print_opt,
.print_help = amt_print_help,
};

View File

@ -198,6 +198,7 @@ ip-link \- network device configuration
.ti -8 .ti -8
.IR TYPE " := [ " .IR TYPE " := [ "
.BR amt " | "
.BR bridge " | " .BR bridge " | "
.BR bond " | " .BR bond " | "
.BR can " | " .BR can " | "
@ -364,6 +365,9 @@ Link types:
.BR bareudp .BR bareudp
- Bare UDP L3 encapsulation support - Bare UDP L3 encapsulation support
.sp .sp
.BR amt
- Automatic Multicast Tunneling (AMT)
.sp
.BR macsec .BR macsec
- Interface for IEEE 802.1AE MAC Security (MACsec) - Interface for IEEE 802.1AE MAC Security (MACsec)
.sp .sp
@ -1344,6 +1348,48 @@ When
is "ipv4", this allows the tunnel to also handle IPv6. This option is disabled is "ipv4", this allows the tunnel to also handle IPv6. This option is disabled
by default. by default.
.TP
AMT Type Support
For a link of type
.I AMT
the following additional arguments are supported:
.BI "ip link add " DEVICE
.BI type " AMT " discovery " IPADDR " mode " { " gateway " | " relay " } "
.BI local " IPADDR " dev " PHYS_DEV " [
.BI relay_port " PORT " ]
[
.BI gateway_port " PORT " ]
[
.BI max_tunnels " NUMBER "
]
.in +8
.sp
.BI discovery " IPADDR"
- specifies the unicast discovery IP address to use to find remote IP address.
.BR mode " { " gateway " | " relay " } "
- specifies the role of AMT, Gateway or Relay
.BI local " IPADDR "
- specifies the source IP address to use in outgoing packets.
.BI dev " PHYS_DEV "
- specifies the underlying physical interface from which transform traffic
is sent and received.
.BI relay_port " PORT "
- specifies the UDP Relay port to communicate to the Relay.
.BI gateway_port " PORT "
- specifies the UDP Gateway port to communicate to the Gateway.
.BI max_tunnels " NUMBER "
- specifies the maximum number of tunnels.
.in -8
.TP .TP
MACVLAN and MACVTAP Type Support MACVLAN and MACVTAP Type Support
For a link of type For a link of type