1 /* iplink_vrf.c VRF device support
3 * This program is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU General Public License
5 * as published by the Free Software Foundation; either version
6 * 2 of the License, or (at your option) any later version.
8 * Authors: Shrijeet Mukherjee <shm@cumulusnetworks.com>
14 #include <sys/socket.h>
15 #include <linux/if_link.h>
20 #include "ip_common.h"
22 static void vrf_explain(FILE *f
)
24 fprintf(f
, "Usage: ... vrf table TABLEID\n");
27 static void explain(void)
32 static int vrf_parse_opt(struct link_util
*lu
, int argc
, char **argv
,
36 if (matches(*argv
, "table") == 0) {
41 if (rtnl_rttable_a2n(&table
, *argv
))
42 invarg("invalid table ID\n", *argv
);
43 addattr32(n
, 1024, IFLA_VRF_TABLE
, table
);
44 } else if (matches(*argv
, "help") == 0) {
48 fprintf(stderr
, "vrf: unknown option \"%s\"?\n",
59 static void vrf_print_opt(struct link_util
*lu
, FILE *f
, struct rtattr
*tb
[])
64 if (tb
[IFLA_VRF_TABLE
])
68 rta_getattr_u32(tb
[IFLA_VRF_TABLE
]));
71 static void vrf_slave_print_opt(struct link_util
*lu
, FILE *f
,
77 if (tb
[IFLA_VRF_PORT_TABLE
]) {
81 rta_getattr_u32(tb
[IFLA_VRF_PORT_TABLE
]));
85 static void vrf_print_help(struct link_util
*lu
, int argc
, char **argv
,
91 struct link_util vrf_link_util
= {
93 .maxattr
= IFLA_VRF_MAX
,
94 .parse_opt
= vrf_parse_opt
,
95 .print_opt
= vrf_print_opt
,
96 .print_help
= vrf_print_help
,
99 struct link_util vrf_slave_link_util
= {
101 .maxattr
= IFLA_VRF_PORT_MAX
,
102 .print_opt
= vrf_slave_print_opt
,
105 /* returns table id if name is a VRF device */
106 __u32
ipvrf_get_table(const char *name
)
114 .nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifinfomsg
)),
115 .nlmsg_flags
= NLM_F_REQUEST
,
116 .nlmsg_type
= RTM_GETLINK
,
119 .ifi_family
= preferred_family
,
126 struct rtattr
*tb
[IFLA_MAX
+1];
127 struct rtattr
*li
[IFLA_INFO_MAX
+1];
128 struct rtattr
*vrf_attr
[IFLA_VRF_MAX
+ 1];
129 struct ifinfomsg
*ifi
;
133 addattr_l(&req
.n
, sizeof(req
), IFLA_IFNAME
, name
, strlen(name
) + 1);
135 if (rtnl_talk_suppress_rtnl_errmsg(&rth
, &req
.n
,
136 &answer
.n
, sizeof(answer
)) < 0) {
137 /* special case "default" vrf to be the main table */
138 if (errno
== ENODEV
&& !strcmp(name
, "default"))
139 if (rtnl_rttable_a2n(&tb_id
, "main"))
141 "BUG: RTTable \"main\" not found.\n");
146 ifi
= NLMSG_DATA(&answer
.n
);
147 len
= answer
.n
.nlmsg_len
- NLMSG_LENGTH(sizeof(*ifi
));
149 fprintf(stderr
, "BUG: Invalid response to link query.\n");
153 parse_rtattr(tb
, IFLA_MAX
, IFLA_RTA(ifi
), len
);
155 if (!tb
[IFLA_LINKINFO
])
158 parse_rtattr_nested(li
, IFLA_INFO_MAX
, tb
[IFLA_LINKINFO
]);
160 if (!li
[IFLA_INFO_KIND
] || !li
[IFLA_INFO_DATA
])
163 if (strcmp(RTA_DATA(li
[IFLA_INFO_KIND
]), "vrf"))
166 parse_rtattr_nested(vrf_attr
, IFLA_VRF_MAX
, li
[IFLA_INFO_DATA
]);
167 if (vrf_attr
[IFLA_VRF_TABLE
])
168 tb_id
= rta_getattr_u32(vrf_attr
[IFLA_VRF_TABLE
]);
171 fprintf(stderr
, "BUG: VRF %s is missing table id\n", name
);
176 int name_is_vrf(const char *name
)
184 .nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifinfomsg
)),
185 .nlmsg_flags
= NLM_F_REQUEST
,
186 .nlmsg_type
= RTM_GETLINK
,
189 .ifi_family
= preferred_family
,
196 struct rtattr
*tb
[IFLA_MAX
+1];
197 struct rtattr
*li
[IFLA_INFO_MAX
+1];
198 struct ifinfomsg
*ifi
;
201 addattr_l(&req
.n
, sizeof(req
), IFLA_IFNAME
, name
, strlen(name
) + 1);
203 if (rtnl_talk_suppress_rtnl_errmsg(&rth
, &req
.n
,
204 &answer
.n
, sizeof(answer
)) < 0)
207 ifi
= NLMSG_DATA(&answer
.n
);
208 len
= answer
.n
.nlmsg_len
- NLMSG_LENGTH(sizeof(*ifi
));
210 fprintf(stderr
, "BUG: Invalid response to link query.\n");
214 parse_rtattr(tb
, IFLA_MAX
, IFLA_RTA(ifi
), len
);
216 if (!tb
[IFLA_LINKINFO
])
219 parse_rtattr_nested(li
, IFLA_INFO_MAX
, tb
[IFLA_LINKINFO
]);
221 if (!li
[IFLA_INFO_KIND
])
224 if (strcmp(RTA_DATA(li
[IFLA_INFO_KIND
]), "vrf"))
227 return ifi
->ifi_index
;