1de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz/*
2de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz * iplink_ipoib.c	IPoIB device support
3de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz *
4de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz *              This program is free software; you can redistribute it and/or
5de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz *              modify it under the terms of the GNU General Public License
6de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz *              as published by the Free Software Foundation; either version
7de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz *              2 of the License, or (at your option) any later version.
8de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz *
9de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz * Authors:     Or Gerlitz <ogerlitz@mellanox.com>
10de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz *		copied iflink_vlan.c authored by Patrick McHardy <kaber@trash.net>
11de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz */
12de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz
13de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz#include <stdio.h>
14de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz#include <stdlib.h>
15de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz#include <string.h>
16de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz#include <linux/if_link.h>
17de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz
18de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz#include "rt_names.h"
19de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz#include "utils.h"
20de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz#include "ip_common.h"
21de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz
22561e650eff679296d3f4c12657721ae769cbc187vadimkstatic void print_explain(FILE *f)
23de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz{
24561e650eff679296d3f4c12657721ae769cbc187vadimk	fprintf(f,
258b47135474cde4f0f8c9991741132b930bf3e192Phil Sutter		"Usage: ... ipoib [ pkey PKEY ]\n"
268b47135474cde4f0f8c9991741132b930bf3e192Phil Sutter		"                 [ mode {datagram | connected} ]\n"
278b47135474cde4f0f8c9991741132b930bf3e192Phil Sutter		"                 [ umcast {0|1} ]\n"
28de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz		"\n"
29de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz		"PKEY  := 0x8001-0xffff\n"
30de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz	);
31de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz}
32de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz
33561e650eff679296d3f4c12657721ae769cbc187vadimkstatic void explain(void)
34561e650eff679296d3f4c12657721ae769cbc187vadimk{
35561e650eff679296d3f4c12657721ae769cbc187vadimk	print_explain(stderr);
36561e650eff679296d3f4c12657721ae769cbc187vadimk}
37de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz
38de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitzstatic int mode_arg(void)
39de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz{
4056f5daac98da0c405fdbc52f04afd5de82404bceStephen Hemminger	fprintf(stderr, "Error: argument of \"mode\" must be \"datagram\"or \"connected\"\n");
41de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz	return -1;
42de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz}
43de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz
44de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitzstatic int ipoib_parse_opt(struct link_util *lu, int argc, char **argv,
45de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz			  struct nlmsghdr *n)
46de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz{
47de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz	__u16 pkey, mode, umcast;
48de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz
49de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz	while (argc > 0) {
50de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz		if (matches(*argv, "pkey") == 0) {
51de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz			NEXT_ARG();
52de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz			if (get_u16(&pkey, *argv, 0))
53de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz				invarg("pkey is invalid", *argv);
54de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz			addattr_l(n, 1024, IFLA_IPOIB_PKEY, &pkey, 2);
55de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz		} else if (matches(*argv, "mode") == 0) {
56de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz			NEXT_ARG();
57de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz			if (strcmp(*argv, "datagram") == 0)
58de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz				mode = IPOIB_MODE_DATAGRAM;
59de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz			else if (strcmp(*argv, "connected") == 0)
60de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz				mode = IPOIB_MODE_CONNECTED;
61de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz			else
62de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz				return mode_arg();
63de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz			addattr_l(n, 1024, IFLA_IPOIB_MODE, &mode, 2);
64de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz		} else if (matches(*argv, "umcast") == 0) {
65de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz			NEXT_ARG();
66de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz			if (get_u16(&umcast, *argv, 0))
67de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz				invarg("umcast is invalid", *argv);
68de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz			addattr_l(n, 1024, IFLA_IPOIB_UMCAST, &umcast, 2);
69de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz		} else if (matches(*argv, "help") == 0) {
70de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz			explain();
71de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz			return -1;
72de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz		} else {
7314645ec2310ee7cf6d2f3d5035ac37ec09674e2cKees van Reeuwijk			fprintf(stderr, "ipoib: unknown option \"%s\"?\n", *argv);
74de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz			explain();
75de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz			return -1;
76de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz		}
77de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz		argc--, argv++;
78de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz	}
79de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz
80de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz	return 0;
81de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz}
82de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz
83de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitzstatic void ipoib_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
84de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz{
85de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz	__u16 mode;
86de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz
87de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz	if (!tb)
88de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz		return;
89de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz
90de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz	if (!tb[IFLA_IPOIB_PKEY] ||
91de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz	    RTA_PAYLOAD(tb[IFLA_IPOIB_PKEY]) < sizeof(__u16))
92de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz		return;
93de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz
943bec1cf84efeafe51b32cc93b00dfc5bfb24f277Julien Fortin	__u16 pkey = rta_getattr_u16(tb[IFLA_IPOIB_PKEY]);
953bec1cf84efeafe51b32cc93b00dfc5bfb24f277Julien Fortin
963bec1cf84efeafe51b32cc93b00dfc5bfb24f277Julien Fortin	if (is_json_context()) {
973bec1cf84efeafe51b32cc93b00dfc5bfb24f277Julien Fortin		SPRINT_BUF(b1);
983bec1cf84efeafe51b32cc93b00dfc5bfb24f277Julien Fortin
993bec1cf84efeafe51b32cc93b00dfc5bfb24f277Julien Fortin		snprintf(b1, sizeof(b1), "%#.4x", pkey);
1003bec1cf84efeafe51b32cc93b00dfc5bfb24f277Julien Fortin		print_string(PRINT_JSON, "key", NULL, b1);
1013bec1cf84efeafe51b32cc93b00dfc5bfb24f277Julien Fortin	} else {
1023bec1cf84efeafe51b32cc93b00dfc5bfb24f277Julien Fortin		fprintf(f, "pkey  %#.4x ", pkey);
1033bec1cf84efeafe51b32cc93b00dfc5bfb24f277Julien Fortin	}
104de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz
105de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz	if (!tb[IFLA_IPOIB_MODE] ||
106de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz	    RTA_PAYLOAD(tb[IFLA_IPOIB_MODE]) < sizeof(__u16))
107de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz		return;
108de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz
109de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz	mode = rta_getattr_u16(tb[IFLA_IPOIB_MODE]);
1103bec1cf84efeafe51b32cc93b00dfc5bfb24f277Julien Fortin
1113bec1cf84efeafe51b32cc93b00dfc5bfb24f277Julien Fortin	const char *mode_str =
112de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz		mode == IPOIB_MODE_DATAGRAM ? "datagram" :
1133bec1cf84efeafe51b32cc93b00dfc5bfb24f277Julien Fortin		mode == IPOIB_MODE_CONNECTED ? "connected" : "unknown";
1143bec1cf84efeafe51b32cc93b00dfc5bfb24f277Julien Fortin
1153bec1cf84efeafe51b32cc93b00dfc5bfb24f277Julien Fortin	print_string(PRINT_ANY, "mode", "mode  %s ", mode_str);
116de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz
117de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz	if (!tb[IFLA_IPOIB_UMCAST] ||
118de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz	    RTA_PAYLOAD(tb[IFLA_IPOIB_UMCAST]) < sizeof(__u16))
119de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz		return;
120de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz
1213bec1cf84efeafe51b32cc93b00dfc5bfb24f277Julien Fortin	__u16 umcast = rta_getattr_u16(tb[IFLA_IPOIB_UMCAST]);
1223bec1cf84efeafe51b32cc93b00dfc5bfb24f277Julien Fortin
1233bec1cf84efeafe51b32cc93b00dfc5bfb24f277Julien Fortin	if (is_json_context()) {
1243bec1cf84efeafe51b32cc93b00dfc5bfb24f277Julien Fortin		SPRINT_BUF(b1);
1253bec1cf84efeafe51b32cc93b00dfc5bfb24f277Julien Fortin
1263bec1cf84efeafe51b32cc93b00dfc5bfb24f277Julien Fortin		snprintf(b1, sizeof(b1), "%.4x", umcast);
1273bec1cf84efeafe51b32cc93b00dfc5bfb24f277Julien Fortin		print_string(PRINT_JSON, "umcast", NULL, b1);
1283bec1cf84efeafe51b32cc93b00dfc5bfb24f277Julien Fortin	} else {
1293bec1cf84efeafe51b32cc93b00dfc5bfb24f277Julien Fortin		fprintf(f, "umcast  %.4x ", umcast);
1303bec1cf84efeafe51b32cc93b00dfc5bfb24f277Julien Fortin	}
131de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz}
132de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz
133561e650eff679296d3f4c12657721ae769cbc187vadimkstatic void ipoib_print_help(struct link_util *lu, int argc, char **argv,
134561e650eff679296d3f4c12657721ae769cbc187vadimk	FILE *f)
135561e650eff679296d3f4c12657721ae769cbc187vadimk{
136561e650eff679296d3f4c12657721ae769cbc187vadimk	print_explain(f);
137561e650eff679296d3f4c12657721ae769cbc187vadimk}
138561e650eff679296d3f4c12657721ae769cbc187vadimk
139de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitzstruct link_util ipoib_link_util = {
140de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz	.id		= "ipoib",
141de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz	.maxattr	= IFLA_IPOIB_MAX,
142de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz	.parse_opt	= ipoib_parse_opt,
143de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz	.print_opt	= ipoib_print_opt,
144561e650eff679296d3f4c12657721ae769cbc187vadimk	.print_help	= ipoib_print_help,
145de0389935f8c4abdbe275564db05e7ee3535ef36Or Gerlitz};
146