1 /* 2 * iplink_geneve.c GENEVE device support 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 7 * 2 of the License, or (at your option) any later version. 8 * 9 * Authors: John W. Linville <linville (at) tuxdriver.com> 10 */ 11 12 #include <stdio.h> 13 14 #include "rt_names.h" 15 #include "utils.h" 16 #include "ip_common.h" 17 18 static void print_explain(FILE *f) 19 { 20 fprintf(f, "Usage: ... geneve id VNI remote ADDR\n"); 21 fprintf(f, " [ ttl TTL ] [ tos TOS ]\n"); 22 fprintf(f, "\n"); 23 fprintf(f, "Where: VNI := 0-16777215\n"); 24 fprintf(f, " ADDR := IP_ADDRESS\n"); 25 fprintf(f, " TOS := { NUMBER | inherit }\n"); 26 fprintf(f, " TTL := { 1..255 | inherit }\n"); 27 } 28 29 static void explain(void) 30 { 31 print_explain(stderr); 32 } 33 34 static int geneve_parse_opt(struct link_util *lu, int argc, char **argv, 35 struct nlmsghdr *n) 36 { 37 __u32 vni = 0; 38 int vni_set = 0; 39 __u32 daddr = 0; 40 struct in6_addr daddr6 = IN6ADDR_ANY_INIT; 41 __u8 ttl = 0; 42 __u8 tos = 0; 43 44 while (argc > 0) { 45 if (!matches(*argv, "id") || 46 !matches(*argv, "vni")) { 47 NEXT_ARG(); 48 if (get_u32(&vni, *argv, 0) || 49 vni >= 1u << 24) 50 invarg("invalid id", *argv); 51 vni_set = 1; 52 } else if (!matches(*argv, "remote")) { 53 NEXT_ARG(); 54 if (!inet_get_addr(*argv, &daddr, &daddr6)) { 55 fprintf(stderr, "Invalid address \"%s\"\n", *argv); 56 return -1; 57 } 58 if (IN6_IS_ADDR_MULTICAST(&daddr6) || IN_MULTICAST(ntohl(daddr))) 59 invarg("invalid remote address", *argv); 60 } else if (!matches(*argv, "ttl") || 61 !matches(*argv, "hoplimit")) { 62 unsigned uval; 63 64 NEXT_ARG(); 65 if (strcmp(*argv, "inherit") != 0) { 66 if (get_unsigned(&uval, *argv, 0)) 67 invarg("invalid TTL", *argv); 68 if (uval > 255) 69 invarg("TTL must be <= 255", *argv); 70 ttl = uval; 71 } 72 } else if (!matches(*argv, "tos") || 73 !matches(*argv, "dsfield")) { 74 __u32 uval; 75 76 NEXT_ARG(); 77 if (strcmp(*argv, "inherit") != 0) { 78 if (rtnl_dsfield_a2n(&uval, *argv)) 79 invarg("bad TOS value", *argv); 80 tos = uval; 81 } else 82 tos = 1; 83 } else if (matches(*argv, "help") == 0) { 84 explain(); 85 return -1; 86 } else { 87 fprintf(stderr, "geneve: unknown command \"%s\"?\n", *argv); 88 explain(); 89 return -1; 90 } 91 argc--, argv++; 92 } 93 94 if (!vni_set) { 95 fprintf(stderr, "geneve: missing virtual network identifier\n"); 96 return -1; 97 } 98 99 if (!daddr && memcmp(&daddr6, &in6addr_any, sizeof(daddr6)) == 0) { 100 fprintf(stderr, "geneve: remote link partner not specified\n"); 101 return -1; 102 } 103 104 addattr32(n, 1024, IFLA_GENEVE_ID, vni); 105 if (daddr) 106 addattr_l(n, 1024, IFLA_GENEVE_REMOTE, &daddr, 4); 107 if (memcmp(&daddr6, &in6addr_any, sizeof(daddr6)) != 0) 108 addattr_l(n, 1024, IFLA_GENEVE_REMOTE6, &daddr6, sizeof(struct in6_addr)); 109 addattr8(n, 1024, IFLA_GENEVE_TTL, ttl); 110 addattr8(n, 1024, IFLA_GENEVE_TOS, tos); 111 112 return 0; 113 } 114 115 static void geneve_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) 116 { 117 __u32 vni; 118 char s1[1024]; 119 __u8 tos; 120 121 if (!tb) 122 return; 123 124 if (!tb[IFLA_GENEVE_ID] || 125 RTA_PAYLOAD(tb[IFLA_GENEVE_ID]) < sizeof(__u32)) 126 return; 127 128 vni = rta_getattr_u32(tb[IFLA_GENEVE_ID]); 129 fprintf(f, "id %u ", vni); 130 131 if (tb[IFLA_GENEVE_REMOTE]) { 132 __be32 addr = rta_getattr_u32(tb[IFLA_GENEVE_REMOTE]); 133 if (addr) 134 fprintf(f, "remote %s ", 135 format_host(AF_INET, 4, &addr, s1, sizeof(s1))); 136 } else if (tb[IFLA_GENEVE_REMOTE6]) { 137 struct in6_addr addr; 138 memcpy(&addr, RTA_DATA(tb[IFLA_GENEVE_REMOTE6]), sizeof(struct in6_addr)); 139 if (memcmp(&addr, &in6addr_any, sizeof(addr)) != 0) { 140 if (IN6_IS_ADDR_MULTICAST(&addr)) 141 fprintf(f, "remote %s ", 142 format_host(AF_INET6, sizeof(struct in6_addr), &addr, s1, sizeof(s1))); 143 } 144 } 145 146 if (tb[IFLA_GENEVE_TTL]) { 147 __u8 ttl = rta_getattr_u8(tb[IFLA_GENEVE_TTL]); 148 if (ttl) 149 fprintf(f, "ttl %d ", ttl); 150 } 151 152 if (tb[IFLA_GENEVE_TOS] && 153 (tos = rta_getattr_u8(tb[IFLA_GENEVE_TOS]))) { 154 if (tos == 1) 155 fprintf(f, "tos inherit "); 156 else 157 fprintf(f, "tos %#x ", tos); 158 } 159 } 160 161 static void geneve_print_help(struct link_util *lu, int argc, char **argv, 162 FILE *f) 163 { 164 print_explain(f); 165 } 166 167 struct link_util geneve_link_util = { 168 .id = "geneve", 169 .maxattr = IFLA_GENEVE_MAX, 170 .parse_opt = geneve_parse_opt, 171 .print_opt = geneve_print_opt, 172 .print_help = geneve_print_help, 173 }; 174