13f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala/*
23f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala * iplink_macvtap.c	macvtap device support
33f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala *
43f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala *              This program is free software; you can redistribute it and/or
53f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala *              modify it under the terms of the GNU General Public License
63f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala *              as published by the Free Software Foundation; either version
73f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala *              2 of the License, or (at your option) any later version.
83f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala */
93f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala
103f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala#include <stdio.h>
113f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala#include <stdlib.h>
123f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala#include <string.h>
133f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala#include <sys/socket.h>
143f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala#include <linux/if_link.h>
153f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala
163f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala#include "rt_names.h"
173f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala#include "utils.h"
183f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala#include "ip_common.h"
193f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala
203f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudralastatic void explain(void)
213f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala{
223f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala	fprintf(stderr,
23f0612d566b8bb76866fa772076412d290ed4cf5eSridhar Samudrala		"Usage: ... macvtap mode { private | vepa | bridge | passthru }\n"
243f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala	);
253f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala}
263f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala
273f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudralastatic int mode_arg(void)
283f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala{
293f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala        fprintf(stderr, "Error: argument of \"mode\" must be \"private\", "
30f0612d566b8bb76866fa772076412d290ed4cf5eSridhar Samudrala		"\"vepa\", \"bridge\" or \"passthru\" \n");
313f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala        return -1;
323f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala}
333f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala
343f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudralastatic int macvtap_parse_opt(struct link_util *lu, int argc, char **argv,
353f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala			  struct nlmsghdr *n)
363f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala{
373f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala	while (argc > 0) {
383f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala		if (matches(*argv, "mode") == 0) {
393f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala			__u32 mode = 0;
403f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala			NEXT_ARG();
413f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala
423f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala			if (strcmp(*argv, "private") == 0)
433f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala				mode = MACVLAN_MODE_PRIVATE;
443f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala			else if (strcmp(*argv, "vepa") == 0)
453f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala				mode = MACVLAN_MODE_VEPA;
463f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala			else if (strcmp(*argv, "bridge") == 0)
473f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala				mode = MACVLAN_MODE_BRIDGE;
48f0612d566b8bb76866fa772076412d290ed4cf5eSridhar Samudrala			else if (strcmp(*argv, "passthru") == 0)
49f0612d566b8bb76866fa772076412d290ed4cf5eSridhar Samudrala				mode = MACVLAN_MODE_PASSTHRU;
503f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala			else
513f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala				return mode_arg();
523f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala
533f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala			addattr32(n, 1024, IFLA_MACVLAN_MODE, mode);
543f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala		} else if (matches(*argv, "help") == 0) {
553f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala			explain();
563f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala			return -1;
573f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala		} else {
583f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala			fprintf(stderr, "macvtap: what is \"%s\"?\n", *argv);
593f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala			explain();
603f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala			return -1;
613f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala		}
623f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala		argc--, argv++;
633f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala	}
643f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala
653f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala	return 0;
663f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala}
673f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala
683f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudralastatic void macvtap_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
693f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala{
703f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala	__u32 mode;
713f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala
723f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala	if (!tb)
733f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala		return;
743f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala
753f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala	if (!tb[IFLA_MACVLAN_MODE] ||
763f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala	    RTA_PAYLOAD(tb[IFLA_MACVLAN_MODE]) < sizeof(__u32))
773f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala		return;
783f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala
79ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger	mode = rta_getattr_u32(tb[IFLA_VLAN_ID]);
803f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala	fprintf(f, " mode %s ",
813f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala		  mode == MACVLAN_MODE_PRIVATE ? "private"
823f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala		: mode == MACVLAN_MODE_VEPA    ? "vepa"
833f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala		: mode == MACVLAN_MODE_BRIDGE  ? "bridge"
84f0612d566b8bb76866fa772076412d290ed4cf5eSridhar Samudrala		: mode == MACVLAN_MODE_PASSTHRU  ? "passthru"
853f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala		:				 "unknown");
863f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala}
873f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala
883f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudralastruct link_util macvtap_link_util = {
893f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala	.id		= "macvtap",
903f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala	.maxattr	= IFLA_MACVLAN_MAX,
913f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala	.parse_opt	= macvtap_parse_opt,
923f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala	.print_opt	= macvtap_print_opt,
933f0a7b4c4f0a6c5462ad55b7fa4445c2d485f435Sridhar Samudrala};
94