std::deque<rtnl_neigh *> nl_bridge::get_fdb_entries_of_port(rtnl_link *br_port, uint16_t vid) { std::unique_ptr<rtnl_neigh, decltype(&rtnl_neigh_put)> filter( rtnl_neigh_alloc(), rtnl_neigh_put); rtnl_neigh_set_ifindex(filter.get(), rtnl_link_get_ifindex(br_port)); rtnl_neigh_set_master(filter.get(), rtnl_link_get_ifindex(bridge)); rtnl_neigh_set_vlan(filter.get(), vid); rtnl_neigh_set_family(filter.get(), AF_BRIDGE); std::deque<rtnl_neigh *> neighs; nl_cache_foreach_filter( nl->get_cache(cnetlink::NL_NEIGH_CACHE), OBJ_CAST(filter.get()), [](struct nl_object *o, void *arg) { std::deque<rtnl_neigh *> *neighs = (std::deque<rtnl_neigh *> *)arg; neighs->push_back(NEIGH_CAST(o)); VLOG(3) << "needs to be updated " << o; }, &neighs); return neighs; }
int main(int argc, char *argv[]) { struct rtnl_qdisc *qdisc; struct rtnl_tc *tc; struct nl_cache *link_cache, *qdisc_cache; int nfilter = 0; sock = nl_cli_alloc_socket(); nl_cli_connect(sock, NETLINK_ROUTE); link_cache = nl_cli_link_alloc_cache(sock); qdisc_cache = nl_cli_qdisc_alloc_cache(sock); qdisc = nl_cli_qdisc_alloc(); tc = (struct rtnl_tc *) qdisc; for (;;) { int c, optidx = 0; enum { ARG_YES = 257, ARG_INTERACTIVE = 258, }; static struct option long_opts[] = { { "interactive", 0, 0, ARG_INTERACTIVE }, { "yes", 0, 0, ARG_YES }, { "quiet", 0, 0, 'q' }, { "help", 0, 0, 'h' }, { "version", 0, 0, 'v' }, { "dev", 1, 0, 'd' }, { "parent", 1, 0, 'p' }, { "id", 1, 0, 'i' }, { "kind", 1, 0, 'k' }, { 0, 0, 0, 0 } }; c = getopt_long(argc, argv, "qhvd:p:i:k:", long_opts, &optidx); if (c == -1) break; switch (c) { case '?': nl_cli_fatal(EINVAL, "Invalid options"); case ARG_INTERACTIVE: interactive = 1; break; case ARG_YES: default_yes = 1; break; case 'q': quiet = 1; break; case 'h': print_usage(); break; case 'v': nl_cli_print_version(); break; case 'd': nfilter++; nl_cli_tc_parse_dev(tc, link_cache, optarg); break; case 'p': nfilter++; nl_cli_tc_parse_parent(tc, optarg); break; case 'i': nfilter++; nl_cli_tc_parse_handle(tc, optarg, 0); break; case 'k': nfilter++; nl_cli_tc_parse_kind(tc, optarg); break; } } if (nfilter == 0 && !interactive && !default_yes) { nl_cli_fatal(EINVAL, "You are attempting to delete all qdiscs on all devices.\n" "If you want to proceed, run nl-qdisc-delete --yes.\n" "Aborting..."); } nl_cache_foreach_filter(qdisc_cache, OBJ_CAST(qdisc), delete_cb, NULL); if (!quiet) printf("Deleted %d qdiscs\n", deleted); return 0; }
TNlLink::TNlLink(std::shared_ptr<TNl> sock, struct rtnl_link *link) { Nl = sock; Link = link; nl_object_get(OBJ_CAST(Link)); }
static void dock_reshape(WDock *dock) { int outline_style; if(!ioncore_g.shape_extension) return; dock_get_outline_style(dock, &outline_style); switch(outline_style){ case DOCK_OUTLINE_STYLE_NONE: case DOCK_OUTLINE_STYLE_EACH: { WDockApp *dockapp; /* Start with an empty set */ XShapeCombineRectangles(ioncore_g.dpy, ((WWindow*)dock)->win, ShapeBounding, 0, 0, NULL, 0, ShapeSet, 0); /* Union with dockapp shapes */ for(dockapp=dock->dockapps; dockapp!=NULL; dockapp=dockapp->next){ WClientWin *cwin=OBJ_CAST(dockapp->reg, WClientWin); if(outline_style==DOCK_OUTLINE_STYLE_EACH && dockapp->draw_border){ /* Union with border shape */ XRectangle tile_rect; tile_rect.x=dockapp->border_geom.x; tile_rect.y=dockapp->border_geom.y; tile_rect.width=dockapp->border_geom.w; tile_rect.height=dockapp->border_geom.h; XShapeCombineRectangles(ioncore_g.dpy, ((WWindow*)dock)->win, ShapeBounding, 0, 0, &tile_rect, 1, ShapeUnion, 0); }else if(cwin!=NULL){ /* Union with dockapp shape */ int count; int ordering; XRectangle *rects=XShapeGetRectangles(ioncore_g.dpy, cwin->win, ShapeBounding, &count, &ordering); if(rects!=NULL){ WRectangle dockapp_geom=REGION_GEOM(cwin); XShapeCombineRectangles(ioncore_g.dpy, ((WWindow*)dock)->win, ShapeBounding, dockapp_geom.x, dockapp_geom.y, rects, count, ShapeUnion, ordering); XFree(rects); } } } } break; case DOCK_OUTLINE_STYLE_ALL: { WRectangle geom; XRectangle rect; geom=REGION_GEOM(dock); rect.x=0; rect.y=0; rect.width=geom.w; rect.height=geom.h; XShapeCombineRectangles(ioncore_g.dpy, ((WWindow*)dock)->win, ShapeBounding, 0, 0, &rect, 1, ShapeSet, 0); } break; } }
int main(int argc, char *argv[]) { struct nl_sock *sock; struct rtnl_route *route; struct nl_dump_params dp = { .dp_type = NL_DUMP_LINE, .dp_fd = stdout, }; int err = 1; sock = nl_cli_alloc_socket(); nl_cli_connect(sock, NETLINK_ROUTE); link_cache = nl_cli_link_alloc_cache(sock); route_cache = nl_cli_route_alloc_cache(sock, 0); route = nl_cli_route_alloc(); for (;;) { int c, optidx = 0; enum { ARG_FAMILY = 257, ARG_SRC = 258, ARG_IIF, ARG_PREF_SRC, ARG_METRICS, ARG_PRIORITY, ARG_SCOPE, ARG_PROTOCOL, ARG_TYPE, }; static struct option long_opts[] = { { "quiet", 0, 0, 'q' }, { "help", 0, 0, 'h' }, { "version", 0, 0, 'v' }, { "dst", 1, 0, 'd' }, { "nexthop", 1, 0, 'n' }, { "table", 1, 0, 't' }, { "family", 1, 0, ARG_FAMILY }, { "src", 1, 0, ARG_SRC }, { "iif", 1, 0, ARG_IIF }, { "pref-src", 1, 0, ARG_PREF_SRC }, { "metrics", 1, 0, ARG_METRICS }, { "priority", 1, 0, ARG_PRIORITY }, { "scope", 1, 0, ARG_SCOPE }, { "protocol", 1, 0, ARG_PROTOCOL }, { "type", 1, 0, ARG_TYPE }, { 0, 0, 0, 0 } }; c = getopt_long(argc, argv, "qhvd:n:t:", long_opts, &optidx); if (c == -1) break; switch (c) { case 'q': quiet = 1; break; case 'h': print_usage(); break; case 'v': nl_cli_print_version(); break; case 'd': nl_cli_route_parse_dst(route, optarg); break; case 'n': nl_cli_route_parse_nexthop(route, optarg, link_cache); break; case 't': nl_cli_route_parse_table(route, optarg); break; case ARG_FAMILY: nl_cli_route_parse_family(route, optarg); break; case ARG_SRC: nl_cli_route_parse_src(route, optarg); break; case ARG_IIF: nl_cli_route_parse_iif(route, optarg, link_cache); break; case ARG_PREF_SRC: nl_cli_route_parse_pref_src(route, optarg); break; case ARG_METRICS: nl_cli_route_parse_metric(route, optarg); break; case ARG_PRIORITY: nl_cli_route_parse_prio(route, optarg); break; case ARG_SCOPE: nl_cli_route_parse_scope(route, optarg); break; case ARG_PROTOCOL: nl_cli_route_parse_protocol(route, optarg); break; case ARG_TYPE: nl_cli_route_parse_type(route, optarg); break; } } if ((err = rtnl_route_add(sock, route, NLM_F_EXCL)) < 0) nl_cli_fatal(err, "Unable to add route: %s", nl_geterror(err)); if (!quiet) { printf("Added "); nl_object_dump(OBJ_CAST(route), &dp); } return 0; }
int main(int argc, char *argv[]) { struct nl_sock *sock; struct nl_cache *link_cache, *route_cache; struct rtnl_route *route; struct nl_dump_params params = { .dp_fd = stdout, .dp_type = NL_DUMP_LINE, }; int print_cache = 0; sock = nl_cli_alloc_socket(); nl_cli_connect(sock, NETLINK_ROUTE); link_cache = nl_cli_link_alloc_cache(sock); route = nl_cli_route_alloc(); for (;;) { int c, optidx = 0; enum { ARG_FAMILY = 257, ARG_SRC = 258, ARG_IIF, ARG_PREF_SRC, ARG_METRICS, ARG_PRIORITY, ARG_SCOPE, ARG_PROTOCOL, ARG_TYPE, }; static struct option long_opts[] = { { "cache", 0, 0, 'c' }, { "format", 1, 0, 'f' }, { "help", 0, 0, 'h' }, { "version", 0, 0, 'v' }, { "dst", 1, 0, 'd' }, { "nexthop", 1, 0, 'n' }, { "table", 1, 0, 't' }, { "family", 1, 0, ARG_FAMILY }, { "src", 1, 0, ARG_SRC }, { "iif", 1, 0, ARG_IIF }, { "pref-src", 1, 0, ARG_PREF_SRC }, { "metrics", 1, 0, ARG_METRICS }, { "priority", 1, 0, ARG_PRIORITY }, { "scope", 1, 0, ARG_SCOPE }, { "protocol", 1, 0, ARG_PROTOCOL }, { "type", 1, 0, ARG_TYPE }, { 0, 0, 0, 0 } }; c = getopt_long(argc, argv, "cf:hvd:n:t:", long_opts, &optidx); if (c == -1) break; switch (c) { case 'c': print_cache = 1; break; case 'f': params.dp_type = nl_cli_parse_dumptype(optarg); break; case 'h': print_usage(); break; case 'v': nl_cli_print_version(); break; case 'd': nl_cli_route_parse_dst(route, optarg); break; case 'n': nl_cli_route_parse_nexthop(route, optarg, link_cache); break; case 't': nl_cli_route_parse_table(route, optarg); break; case ARG_FAMILY: nl_cli_route_parse_family(route, optarg); break; case ARG_SRC: nl_cli_route_parse_src(route, optarg); break; case ARG_IIF: nl_cli_route_parse_iif(route, optarg, link_cache); break; case ARG_PREF_SRC: nl_cli_route_parse_pref_src(route, optarg); break; case ARG_METRICS: nl_cli_route_parse_metric(route, optarg); break; case ARG_PRIORITY: nl_cli_route_parse_prio(route, optarg); break; case ARG_SCOPE: nl_cli_route_parse_scope(route, optarg); break; case ARG_PROTOCOL: nl_cli_route_parse_protocol(route, optarg); break; case ARG_TYPE: nl_cli_route_parse_type(route, optarg); break; } } route_cache = nl_cli_route_alloc_cache(sock, print_cache ? ROUTE_CACHE_CONTENT : 0); nl_cache_dump_filter(route_cache, ¶ms, OBJ_CAST(route)); return 0; }
int main(int argc, char *argv[]) { struct nl_sock *sock; struct rtnl_cls *cls; struct nl_cache *link_cache; struct rtnl_cls_ops *ops; struct cls_module *mod; struct nl_dump_params dp = { .dp_type = NL_DUMP_DETAILS, .dp_fd = stdout, }; char *kind; int err, nlflags = NLM_F_CREATE; sock = nlt_alloc_socket(); nlt_connect(sock, NETLINK_ROUTE); link_cache = nlt_alloc_link_cache(sock); cls = nlt_alloc_cls(); for (;;) { int c, optidx = 0; enum { ARG_PROTO = 257, ARG_PRIO = 258, ARG_ID, }; static struct option long_opts[] = { { "quiet", 0, 0, 'q' }, { "help", 0, 0, 'h' }, { "version", 0, 0, 'v' }, { "dev", 1, 0, 'd' }, { "parent", 1, 0, 'p' }, { "proto", 1, 0, ARG_PROTO }, { "prio", 1, 0, ARG_PRIO }, { "id", 1, 0, ARG_ID }, { 0, 0, 0, 0 } }; c = getopt_long(argc, argv, "+qhva:d:", long_opts, &optidx); if (c == -1) break; switch (c) { case '?': exit(NLE_INVAL); case 'q': quiet = 1; break; case 'h': print_usage(); break; case 'v': nlt_print_version(); break; case 'd': parse_dev(cls, link_cache, optarg); break; case 'p': parse_parent(cls, optarg); break; case ARG_PRIO: parse_prio(cls, optarg); break; case ARG_ID: parse_handle(cls, optarg); break; case ARG_PROTO: parse_proto(cls, optarg); break; } } if (optind >= argc) { print_usage(); fatal(EINVAL, "Missing classifier type"); } kind = argv[optind++]; if ((err = rtnl_cls_set_kind(cls, kind)) < 0) fatal(ENOENT, "Unknown classifier type \"%s\".", kind); ops = rtnl_cls_get_ops(cls); if (!(mod = lookup_cls_mod(ops))) fatal(ENOTSUP, "Classifier type \"%s\" not supported.", kind); mod->parse_argv(cls, argc, argv); printf("Adding "); nl_object_dump(OBJ_CAST(cls), &dp); if ((err = rtnl_cls_add(sock, cls, nlflags)) < 0) fatal(err, "Unable to add classifier: %s", nl_geterror(err)); if (!quiet) { printf("Added "); nl_object_dump(OBJ_CAST(cls), &dp); } return 0; }
int main(int argc, char *argv[]) { struct nl_sock *nl_sock; struct nl_cache *link_cache; int ifindex; int ret = 0; int err = 0; if (argc < 2) { printf("%s ip gw on/off tip\n", argv[0]); return -1; } //link if (err = rtnl_route_read_table_names(ROUTE_TABLE)) { printf("failed to read %s. err = %s\n", ROUTE_TABLE, nl_geterror(err)); return -1;; } nl_sock = nl_socket_alloc(); if (NULL == nl_sock) { printf("failed to alloc netlink handler.\n"); return -1; } if (err = nl_connect(nl_sock, NETLINK_ROUTE)) { printf("failed to connect NETLINK_ROUTE. err = %s\n", nl_geterror(err)); ret = -1; goto release_nl; } if (err = rtnl_link_alloc_cache(nl_sock, AF_INET, &link_cache)) { printf("failed to allocate link cache. err = %s\n", nl_geterror(err)); ret = -1; goto release_nl; } ifindex = rtnl_link_name2i(link_cache, NAME); if (0 == ifindex) { printf("%s - failed to find.\n", NAME); ret = -1; goto release_link_cache; } struct rtnl_link * link = rtnl_link_get(link_cache, ifindex); if (link == NULL) { printf("can't get link.\n"); ret = -1; goto release_link_cache; } //rtnl_link_get_by_name struct nl_addr *lladdr = rtnl_link_get_addr(link); if (NULL == lladdr || AF_LLC != nl_addr_get_family(lladdr)) { printf("failed to get MAC\n"); ret = -1; goto release_link; } uint8_t mac_address[ETHER_ADDR_LEN]; memcpy(mac_address, nl_addr_get_binary_addr(lladdr), ETHER_ADDR_LEN); printf("%02X:%02X:%02X:%02X:%02X:%02X\n", mac_address[0], mac_address[1], mac_address[2], mac_address[3], mac_address[4], mac_address[5]); //addr struct nl_cache * addr_cache; if (err = rtnl_addr_alloc_cache(nl_sock, &addr_cache)) { printf("fail to get addr_cache\n"); ret = -1; goto release_link; } struct rtnl_addr *addr = rtnl_addr_alloc(); rtnl_addr_set_ifindex(addr, ifindex); rtnl_addr_set_family(addr, AF_INET); int prefixlen = 16; nl_cache_foreach_filter(addr_cache, (struct nl_object *)addr, get_ip, &prefixlen); nl_cache_free(addr_cache); uint32_t ipaddr = inet_addr(argv[1]); struct nl_addr * local = nl_addr_build(AF_INET, &ipaddr, sizeof(ipaddr)); rtnl_addr_set_local(addr, local); rtnl_addr_set_ifindex(addr, ifindex); rtnl_addr_set_family(addr, AF_INET); rtnl_addr_set_prefixlen(addr, 32); if (!strcmp(argv[2], "on")) { if (err = rtnl_addr_add(nl_sock, addr, 0)) { printf("fail to add addr %s\n", nl_geterror(err)); ret = -1; goto release_addr; } } else { if (err = rtnl_addr_delete(nl_sock, addr, 0)) { printf("fail to del addr %s\n", nl_geterror(err)); ret = -1; goto release_addr; } } //neigh struct nl_cache * neigh_cache; if (err = rtnl_neigh_alloc_cache(nl_sock, &neigh_cache)) { printf("failed to allocate neighbor cache. err = %s\n", nl_geterror(err)); ret = -1; goto release_neigh_cache; } uint32_t gw = inet_addr(argv[3]); struct nl_addr * gw_addr = nl_addr_build(AF_INET, &gw, sizeof(gw)); struct rtnl_neigh * neigh = rtnl_neigh_get(neigh_cache, ifindex, gw_addr); if (neigh) { // It's optional struct nl_addr * lladdr = rtnl_neigh_get_lladdr(neigh); if (lladdr) { uint8_t mac_address[ETHER_ADDR_LEN]; memcpy(mac_address, nl_addr_get_binary_addr(lladdr), ETHER_ADDR_LEN); printf("gw %02X:%02X:%02X:%02X:%02X:%02X\n", mac_address[0], mac_address[1], mac_address[2], mac_address[3], mac_address[4], mac_address[5]); } } nl_addr_put(gw_addr); //route struct nl_cache *route_cache; if (err = rtnl_route_alloc_cache(nl_sock, AF_INET, 0, &route_cache)) { printf("failed to allocate route cache. err = %s\n", nl_geterror(err)); ret = -1; goto release_neigh_cache; } struct rtnl_route *route = rtnl_route_alloc(); struct nl_addr * taddr; err = nl_addr_parse(argv[4], AF_INET, &taddr); if (err) { printf("failed to get taddr. err = %s\n", nl_geterror(err)); ret = -1; goto release_route_cache; } nl_cache_foreach_filter(route_cache, OBJ_CAST(route), get_route, NULL); /* struct nl_sock *nl_fib_sock; nl_fib_sock = nl_socket_alloc(); if (err = nl_connect(nl_fib_sock, NETLINK_FIB_LOOKUP)) { printf("failed to connect NETLINK_ROUTE. err = %s\n", nl_geterror(err)); ret = -1; goto release_nl; } struct nl_dump_params params = { .dp_fd = stdout, .dp_type = NL_DUMP_DETAILS, }; struct nl_cache *route_cache = flnl_result_alloc_cache(); struct flnl_request *req = flnl_request_alloc(); struct nl_addr * taddr; err = nl_addr_parse(argv[4], AF_INET, &taddr); if (err) { printf("failed to get taddr. err = %s\n", nl_geterror(err)); ret = -1; goto release_route; } int table = RT_TABLE_UNSPEC, scope = RT_SCOPE_UNIVERSE; flnl_request_set_addr(req, taddr); flnl_request_set_table(req, table); flnl_request_set_scope(req, scope); err = flnl_lookup(nl_fib_sock, req, route_cache); if (err) { printf("failed to fib lookup. err = %s\n", nl_geterror(err)); ret = -1; goto release_route_addr; } nl_cache_dump(route_cache, ¶ms); release_route_addr: nl_addr_put(taddr); release_route: nl_cache_free(route_cache); nl_object_put(OBJ_CAST(req)); nl_close(nl_fib_sock); nl_socket_free(nl_fib_sock); */ release_route_cache: nl_cache_free(route_cache); release_neigh_cache: nl_cache_free(neigh_cache); release_addr: nl_addr_put(local); rtnl_addr_put(addr); release_link: rtnl_link_put(link); release_link_cache: nl_cache_free(link_cache); release_nl: nl_close(nl_sock); nl_socket_free(nl_sock); return ret; }
static void handle_class(struct nl_object *obj, void *arg) { struct rtnl_tc *tc = (struct rtnl_tc *) obj; struct element *e; struct rdata *rdata = arg; struct rdata ndata = { .level = rdata->level + 1, }; if (!(e = handle_tc_obj(tc, "class", rdata))) return; ndata.parent = e; if (!strcmp(rtnl_tc_get_kind(tc), "htb")) element_set_txmax(e, rtnl_htb_get_rate((struct rtnl_class *) tc)); find_classes(rtnl_tc_get_handle(tc), &ndata); find_qdiscs(rtnl_tc_get_handle(tc), &ndata); } static void find_qdiscs(uint32_t parent, struct rdata *rdata) { struct rtnl_qdisc *filter; if (!(filter = rtnl_qdisc_alloc())) return; rtnl_tc_set_parent((struct rtnl_tc *) filter, parent); nl_cache_foreach_filter(qdisc_cache, OBJ_CAST(filter), handle_qdisc, rdata); rtnl_qdisc_put(filter); } static void find_cls(int ifindex, uint32_t parent, struct rdata *rdata) { struct nl_cache *cls_cache; if (rtnl_cls_alloc_cache(sock, ifindex, parent, &cls_cache) < 0) return; nl_cache_foreach(cls_cache, handle_cls, rdata); nl_cache_free(cls_cache); } static void find_classes(uint32_t parent, struct rdata *rdata) { struct rtnl_class *filter; if (!(filter = rtnl_class_alloc())) return; rtnl_tc_set_parent((struct rtnl_tc *) filter, parent); nl_cache_foreach_filter(class_cache, OBJ_CAST(filter), handle_class, rdata); rtnl_class_put(filter); } static void handle_qdisc(struct nl_object *obj, void *arg) { struct rtnl_tc *tc = (struct rtnl_tc *) obj; struct element *e; struct rdata *rdata = arg; struct rdata ndata = { .level = rdata->level + 1, }; if (!(e = handle_tc_obj(tc, "qdisc", rdata))) return; ndata.parent = e; find_cls(rtnl_tc_get_ifindex(tc), rtnl_tc_get_handle(tc), &ndata); if (rtnl_tc_get_parent(tc) == TC_H_ROOT) { find_cls(rtnl_tc_get_ifindex(tc), TC_H_ROOT, &ndata); find_classes(TC_H_ROOT, &ndata); } find_classes(rtnl_tc_get_handle(tc), &ndata); } static void handle_tc(struct element *e, struct rtnl_link *link) { struct rtnl_qdisc *qdisc; int ifindex = rtnl_link_get_ifindex(link); struct rdata rdata = { .level = 1, .parent = e, }; if (rtnl_class_alloc_cache(sock, ifindex, &class_cache) < 0) return; qdisc = rtnl_qdisc_get_by_parent(qdisc_cache, ifindex, TC_H_ROOT); if (qdisc) { handle_qdisc(OBJ_CAST(qdisc), &rdata); rtnl_qdisc_put(qdisc); } qdisc = rtnl_qdisc_get_by_parent(qdisc_cache, ifindex, 0); if (qdisc) { handle_qdisc(OBJ_CAST(qdisc), &rdata); rtnl_qdisc_put(qdisc); } qdisc = rtnl_qdisc_get_by_parent(qdisc_cache, ifindex, TC_H_INGRESS); if (qdisc) { handle_qdisc(OBJ_CAST(qdisc), &rdata); rtnl_qdisc_put(qdisc); } nl_cache_free(class_cache); } static void update_link_infos(struct element *e, struct rtnl_link *link) { char buf[64]; snprintf(buf, sizeof(buf), "%u", rtnl_link_get_mtu(link)); element_update_info(e, "MTU", buf); rtnl_link_flags2str(rtnl_link_get_flags(link), buf, sizeof(buf)); element_update_info(e, "Flags", buf); rtnl_link_operstate2str(rtnl_link_get_operstate(link), buf, sizeof(buf)); element_update_info(e, "Operstate", buf); snprintf(buf, sizeof(buf), "%u", rtnl_link_get_ifindex(link)); element_update_info(e, "IfIndex", buf); nl_addr2str(rtnl_link_get_addr(link), buf, sizeof(buf)); element_update_info(e, "Address", buf); nl_addr2str(rtnl_link_get_broadcast(link), buf, sizeof(buf)); element_update_info(e, "Broadcast", buf); rtnl_link_mode2str(rtnl_link_get_linkmode(link), buf, sizeof(buf)); element_update_info(e, "Mode", buf); snprintf(buf, sizeof(buf), "%u", rtnl_link_get_txqlen(link)); element_update_info(e, "TXQlen", buf); nl_af2str(rtnl_link_get_family(link), buf, sizeof(buf)); element_update_info(e, "Family", buf); element_update_info(e, "Alias", rtnl_link_get_ifalias(link) ? : ""); element_update_info(e, "Qdisc", rtnl_link_get_qdisc(link) ? : ""); if (rtnl_link_get_link(link)) { snprintf(buf, sizeof(buf), "%u", rtnl_link_get_link(link)); element_update_info(e, "SlaveOfIndex", buf); } } static void do_link(struct nl_object *obj, void *arg) { struct rtnl_link *link = (struct rtnl_link *) obj; struct element *e, *e_parent = NULL; int i, master_ifindex; if (!cfg_show_all && !(rtnl_link_get_flags(link) & IFF_UP)) { /* FIXME: delete element */ return; } /* Check if the interface is a slave of another interface */ if ((master_ifindex = rtnl_link_get_link(link))) { char parent[IFNAMSIZ+1]; rtnl_link_i2name(link_cache, master_ifindex, parent, sizeof(parent)); e_parent = element_lookup(grp, parent, master_ifindex, NULL, 0); } if (!(e = element_lookup(grp, rtnl_link_get_name(link), rtnl_link_get_ifindex(link), e_parent, ELEMENT_CREAT))) return; if (e->e_flags & ELEMENT_FLAG_CREATED) { if (e->e_parent) e->e_level = e->e_parent->e_level + 1; if (element_set_key_attr(e, "bytes", "packets") || element_set_usage_attr(e, "bytes")) BUG(); /* FIXME: Update link infos every 1s or so */ update_link_infos(e, link); e->e_flags &= ~ELEMENT_FLAG_CREATED; } for (i = 0; i < ARRAY_SIZE(link_attrs); i++) { struct attr_map *m = &link_attrs[i]; uint64_t c_rx = 0, c_tx = 0; int flags = 0; if (m->rxid >= 0) { c_rx = rtnl_link_get_stat(link, m->rxid); flags |= UPDATE_FLAG_RX; } if (m->txid >= 0) { c_tx = rtnl_link_get_stat(link, m->txid); flags |= UPDATE_FLAG_TX; } attr_update(e, m->attrid, c_rx, c_tx, flags); } if (!c_notc) handle_tc(e, link); element_notify_update(e, NULL); element_lifesign(e, 1); } static void netlink_read(void) { int err; if ((err = nl_cache_resync(sock, link_cache, NULL, NULL)) < 0) { fprintf(stderr, "Unable to resync link cache: %s\n", nl_geterror(err)); goto disable; } if ((err = nl_cache_resync(sock, qdisc_cache, NULL, NULL)) < 0) { fprintf(stderr, "Unable to resync qdisc cache: %s\n", nl_geterror(err)); goto disable; } nl_cache_foreach(link_cache, do_link, NULL); return; disable: netlink_ops.m_flags &= ~BMON_MODULE_ENABLED; } static void netlink_shutdown(void) { nl_cache_free(link_cache); nl_cache_free(qdisc_cache); nl_socket_free(sock); }
int main(int argc, char *argv[]) { struct nl_sock *sock; struct rtnl_addr *addr; struct nl_cache *link_cache, *addr_cache; struct nl_dump_params params = { .dp_type = NL_DUMP_LINE, .dp_nl_cb = print_prefix, .dp_fd = stdout, }; int dump_env = 0; sock = nl_cli_alloc_socket(); nl_cli_connect(sock, NETLINK_ROUTE); link_cache = nl_cli_link_alloc_cache(sock); addr_cache = nl_cli_addr_alloc_cache(sock); addr = nl_cli_addr_alloc(); for (;;) { int c, optidx = 0; enum { ARG_FAMILY = 257, ARG_LABEL = 258, ARG_PEER, ARG_SCOPE, ARG_BROADCAST, ARG_DETAILS, ARG_ENV, ARG_PREFIX, ARG_PREFERRED, ARG_VALID, }; static struct option long_opts[] = { { "details", 0, 0, ARG_DETAILS }, { "env", 0, 0, ARG_ENV }, { "prefix", 1, 0, ARG_PREFIX }, { "help", 0, 0, 'h' }, { "version", 0, 0, 'v' }, { "local", 1, 0, 'a' }, { "dev", 1, 0, 'd' }, { "family", 1, 0, ARG_FAMILY }, { "label", 1, 0, ARG_LABEL }, { "peer", 1, 0, ARG_PEER }, { "scope", 1, 0, ARG_SCOPE }, { "broadcast", 1, 0, ARG_BROADCAST }, { "preferred", 1, 0, ARG_PREFERRED }, { "valid", 1, 0, ARG_VALID }, { 0, 0, 0, 0 } }; c = getopt_long(argc, argv, "46hva:d:", long_opts, &optidx); if (c == -1) break; switch (c) { case '?': exit(NLE_INVAL); case '4': rtnl_addr_set_family(addr, AF_INET); break; case '6': rtnl_addr_set_family(addr, AF_INET6); break; case ARG_DETAILS: params.dp_type = NL_DUMP_DETAILS; break; case ARG_ENV: dump_env = 1; break; case ARG_PREFIX: prefix = strdup(optarg); break; case 'h': print_usage(); break; case 'v': nl_cli_print_version(); break; case 'a': nl_cli_addr_parse_local(addr, optarg); break; case 'd': nl_cli_addr_parse_dev(addr, link_cache, optarg); break; case ARG_FAMILY: nl_cli_addr_parse_family(addr, optarg); break; case ARG_LABEL: nl_cli_addr_parse_label(addr, optarg); break; case ARG_PEER: nl_cli_addr_parse_peer(addr, optarg); break; case ARG_SCOPE: nl_cli_addr_parse_scope(addr, optarg); break; case ARG_BROADCAST: nl_cli_addr_parse_broadcast(addr, optarg); break; case ARG_PREFERRED: nl_cli_addr_parse_preferred(addr, optarg); break; case ARG_VALID: nl_cli_addr_parse_valid(addr, optarg); break; } } if (dump_env) nl_cache_foreach_filter(addr_cache, OBJ_CAST(addr), env_dump, ¶ms); else nl_cache_dump_filter(addr_cache, ¶ms, OBJ_CAST(addr)); return 0; }
int main(int argc, char *argv[]) { struct nl_sock *sock; struct nfnl_exp *exp; struct nl_dump_params params = { .dp_type = NL_DUMP_LINE, .dp_fd = stdout, }; int err, nlflags = NLM_F_CREATE; exp = nl_cli_exp_alloc(); for (;;) { int c, optidx = 0; enum { ARG_MARK = 270, ARG_TCP_STATE = 271, ARG_EXPECT_PROTO, ARG_EXPECT_SRC, ARG_EXPECT_SPORT, ARG_EXPECT_DST, ARG_EXPECT_DPORT, ARG_MASTER_PROTO, ARG_MASTER_SRC, ARG_MASTER_SPORT, ARG_MASTER_DST, ARG_MASTER_DPORT, ARG_MASK_PROTO, ARG_MASK_SRC, ARG_MASK_SPORT, ARG_MASK_DST, ARG_MASK_DPORT, ARG_NAT_PROTO, ARG_NAT_SRC, ARG_NAT_SPORT, ARG_NAT_DST, ARG_NAT_DPORT, ARG_NAT_DIR, ARG_TIMEOUT, ARG_HELPER_NAME, ARG_REPLACE, ARG_FLAGS, }; static struct option long_opts[] = { { "replace", 1, 0, ARG_REPLACE }, { "quiet", 0, 0, 'q' }, { "help", 0, 0, 'h' }, { "version", 0, 0, 'v' }, { "id", 1, 0, 'i' }, { "expect-proto", 1, 0, ARG_EXPECT_PROTO }, { "expect-src", 1, 0, ARG_EXPECT_SRC }, { "expect-sport", 1, 0, ARG_EXPECT_SPORT }, { "expect-dst", 1, 0, ARG_EXPECT_DST }, { "expect-dport", 1, 0, ARG_EXPECT_DPORT }, { "master-proto", 1, 0, ARG_MASTER_PROTO }, { "master-src", 1, 0, ARG_MASTER_SRC }, { "master-sport", 1, 0, ARG_MASTER_SPORT }, { "master-dst", 1, 0, ARG_MASTER_DST }, { "master-dport", 1, 0, ARG_MASTER_DPORT }, { "mask-proto", 1, 0, ARG_MASK_PROTO }, { "mask-src", 1, 0, ARG_MASK_SRC }, { "mask-sport", 1, 0, ARG_MASK_SPORT }, { "mask-dst", 1, 0, ARG_MASK_DST }, { "mask-dport", 1, 0, ARG_MASK_DPORT }, { "nat-proto", 1, 0, ARG_NAT_PROTO }, { "nat-src", 1, 0, ARG_NAT_SRC }, { "nat-sport", 1, 0, ARG_NAT_SPORT }, { "nat-dst", 1, 0, ARG_NAT_DST }, { "nat-dport", 1, 0, ARG_NAT_DPORT }, { "nat-dir", 1, 0, ARG_NAT_DIR }, { "family", 1, 0, 'F' }, { "timeout", 1, 0, ARG_TIMEOUT }, { "helper", 1, 0, ARG_HELPER_NAME }, { "flags", 1, 0, ARG_FLAGS}, { 0, 0, 0, 0 } }; c = getopt_long(argc, argv, "46f:hvi:p:F:", long_opts, &optidx); if (c == -1) break; switch (c) { case '?': exit(NLE_INVAL); case ARG_REPLACE: nlflags |= NLM_F_REPLACE; break; case 'q': quiet = 1; break; case '4': nfnl_exp_set_family(exp, AF_INET); break; case '6': nfnl_exp_set_family(exp, AF_INET6); break; case 'h': print_usage(); break; case 'v': nl_cli_print_version(); break; case 'i': nl_cli_exp_parse_id(exp, optarg); break; case ARG_EXPECT_PROTO: nl_cli_exp_parse_l4protonum(exp, NFNL_EXP_TUPLE_EXPECT, optarg); break; case ARG_EXPECT_SRC: nl_cli_exp_parse_src(exp, NFNL_EXP_TUPLE_EXPECT, optarg); break; case ARG_EXPECT_SPORT: nl_cli_exp_parse_src_port(exp, NFNL_EXP_TUPLE_EXPECT, optarg); break; case ARG_EXPECT_DST: nl_cli_exp_parse_dst(exp, NFNL_EXP_TUPLE_EXPECT, optarg); break; case ARG_EXPECT_DPORT: nl_cli_exp_parse_dst_port(exp, NFNL_EXP_TUPLE_EXPECT, optarg); break; case ARG_MASTER_PROTO: nl_cli_exp_parse_l4protonum(exp, NFNL_EXP_TUPLE_MASTER, optarg); break; case ARG_MASTER_SRC: nl_cli_exp_parse_src(exp, NFNL_EXP_TUPLE_MASTER, optarg); break; case ARG_MASTER_SPORT: nl_cli_exp_parse_src_port(exp, NFNL_EXP_TUPLE_MASTER, optarg); break; case ARG_MASTER_DST: nl_cli_exp_parse_dst(exp, NFNL_EXP_TUPLE_MASTER, optarg); break; case ARG_MASTER_DPORT: nl_cli_exp_parse_dst_port(exp, NFNL_EXP_TUPLE_MASTER, optarg); break; case ARG_MASK_PROTO: nl_cli_exp_parse_l4protonum(exp, NFNL_EXP_TUPLE_MASK, optarg); break; case ARG_MASK_SRC: nl_cli_exp_parse_src(exp, NFNL_EXP_TUPLE_MASK, optarg); break; case ARG_MASK_SPORT: nl_cli_exp_parse_src_port(exp, NFNL_EXP_TUPLE_MASK, optarg); break; case ARG_MASK_DST: nl_cli_exp_parse_dst(exp, NFNL_EXP_TUPLE_MASK, optarg); break; case ARG_MASK_DPORT: nl_cli_exp_parse_dst_port(exp, NFNL_EXP_TUPLE_MASK, optarg); break; case ARG_NAT_PROTO: nl_cli_exp_parse_l4protonum(exp, NFNL_EXP_TUPLE_NAT, optarg); break; case ARG_NAT_SRC: nl_cli_exp_parse_src(exp, NFNL_EXP_TUPLE_NAT, optarg); break; case ARG_NAT_SPORT: nl_cli_exp_parse_src_port(exp, NFNL_EXP_TUPLE_NAT, optarg); break; case ARG_NAT_DST: nl_cli_exp_parse_dst(exp, NFNL_EXP_TUPLE_NAT, optarg); break; case ARG_NAT_DPORT: nl_cli_exp_parse_dst_port(exp, NFNL_EXP_TUPLE_NAT, optarg); break; case ARG_NAT_DIR: nl_cli_exp_parse_nat_dir(exp, optarg); break; case 'F': nl_cli_exp_parse_family(exp, optarg); break; case ARG_TIMEOUT: nl_cli_exp_parse_timeout(exp, optarg); break; case ARG_HELPER_NAME: nl_cli_exp_parse_helper_name(exp, optarg); break; case ARG_FLAGS: nl_cli_exp_parse_flags(exp, optarg); break; } } sock = nl_cli_alloc_socket(); nl_cli_connect(sock, NETLINK_NETFILTER); if ((err = nfnl_exp_add(sock, exp, nlflags)) < 0) nl_cli_fatal(err, "Unable to add expectation: %s", nl_geterror(err)); if (!quiet) { printf("Added "); nl_object_dump(OBJ_CAST(exp), ¶ms); } return 0; }
int main(int argc, char *argv[]) { struct nl_sock *sock; struct nl_cache *link_cache; struct rtnl_link *link; struct nl_dump_params params = { .dp_type = NL_DUMP_LINE, .dp_fd = stdout, }; sock = nl_cli_alloc_socket(); nl_cli_connect(sock, NETLINK_ROUTE); link = nl_cli_link_alloc(); for (;;) { int c, optidx = 0; enum { ARG_FAMILY = 257, ARG_MTU = 258, ARG_TXQLEN, ARG_WEIGHT, ARG_DETAILS, ARG_STATS, }; static struct option long_opts[] = { { "details", 0, 0, ARG_DETAILS }, { "stats", 0, 0, ARG_STATS }, { "help", 0, 0, 'h' }, { "version", 0, 0, 'v' }, { "name", 1, 0, 'n' }, { "index", 1, 0, 'i' }, { "family", 1, 0, ARG_FAMILY }, { "mtu", 1, 0, ARG_MTU }, { "txqlen", 1, 0, ARG_TXQLEN }, { "weight", 1, 0, ARG_WEIGHT }, { 0, 0, 0, 0 } }; c = getopt_long(argc, argv, "hvn:i:", long_opts, &optidx); if (c == -1) break; switch (c) { case ARG_DETAILS: params.dp_type = NL_DUMP_DETAILS; break; case ARG_STATS: params.dp_type = NL_DUMP_STATS; break; case 'h': print_usage(); break; case 'v': nl_cli_print_version(); break; case 'n': nl_cli_link_parse_name(link, optarg); break; case 'i': nl_cli_link_parse_ifindex(link, optarg); break; case ARG_FAMILY: nl_cli_link_parse_family(link, optarg); break; case ARG_MTU: nl_cli_link_parse_mtu(link, optarg); break; case ARG_TXQLEN: nl_cli_link_parse_txqlen(link, optarg); break; case ARG_WEIGHT: nl_cli_link_parse_weight(link, optarg); break; } } link_cache = nl_cli_link_alloc_cache_family(sock, rtnl_link_get_family(link)); nl_cache_dump_filter(link_cache, ¶ms, OBJ_CAST(link)); return 0; }
int nl_bridge::learn_source_mac(rtnl_link *br_link, packet *p) { // we still assume vlan filtering bridge assert(rtnl_link_get_family(br_link) == AF_BRIDGE); VLOG(2) << __FUNCTION__ << ": pkt " << p << " on link " << OBJ_CAST(br_link); rtnl_link_bridge_vlan *br_vlan = rtnl_link_bridge_get_port_vlan(br_link); if (br_vlan == nullptr) { LOG(ERROR) << __FUNCTION__ << ": only the vlan filtering bridge is supported"; return -EINVAL; } // parse ether frame and check for vid vlan_hdr *hdr = reinterpret_cast<basebox::vlan_hdr *>(p->data); uint16_t vid = 0; // XXX TODO maybe move this to the utils to have a std lib for parsing the // ether frame switch (ntohs(hdr->eth.h_proto)) { case ETH_P_8021Q: // vid vid = ntohs(hdr->vlan); break; default: // no vid, set vid to pvid vid = br_vlan->pvid; LOG(WARNING) << __FUNCTION__ << ": assuming untagged for ethertype " << std::showbase << std::hex << ntohs(hdr->eth.h_proto); break; } // verify that the vid is in use here if (!is_vid_set(vid, br_vlan->vlan_bitmap)) { LOG(WARNING) << __FUNCTION__ << ": got packet on unconfigured port"; return -ENOTSUP; } // set nl neighbour to NL std::unique_ptr<nl_addr, decltype(&nl_addr_put)> h_src( nl_addr_build(AF_LLC, hdr->eth.h_source, sizeof(hdr->eth.h_source)), nl_addr_put); if (!h_src) { LOG(ERROR) << __FUNCTION__ << ": failed to allocate src mac"; return -ENOMEM; } std::unique_ptr<rtnl_neigh, decltype(&rtnl_neigh_put)> n(rtnl_neigh_alloc(), rtnl_neigh_put); rtnl_neigh_set_ifindex(n.get(), rtnl_link_get_ifindex(br_link)); rtnl_neigh_set_master(n.get(), rtnl_link_get_master(br_link)); rtnl_neigh_set_family(n.get(), AF_BRIDGE); rtnl_neigh_set_vlan(n.get(), vid); rtnl_neigh_set_lladdr(n.get(), h_src.get()); rtnl_neigh_set_flags(n.get(), NTF_MASTER | NTF_EXT_LEARNED); rtnl_neigh_set_state(n.get(), NUD_REACHABLE); // check if entry already exists in cache if (is_mac_in_l2_cache(n.get())) { return 0; } nl_msg *msg = nullptr; rtnl_neigh_build_add_request(n.get(), NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL, &msg); assert(msg); // send the message and create new fdb entry if (nl->send_nl_msg(msg) < 0) { LOG(ERROR) << __FUNCTION__ << ": failed to send netlink message"; return -EINVAL; } // cache the entry if (nl_cache_add(l2_cache.get(), OBJ_CAST(n.get())) < 0) { LOG(ERROR) << __FUNCTION__ << ": failed to add entry to l2_cache " << OBJ_CAST(n.get()); return -EINVAL; } VLOG(2) << __FUNCTION__ << ": learned new source mac " << OBJ_CAST(n.get()); return 0; }
void nl_bridge::update_access_ports(rtnl_link *vxlan_link, rtnl_link *br_link, const uint16_t vid, const uint32_t tunnel_id, const std::deque<rtnl_link *> &bridge_ports, bool add) { // XXX pvid is currently not taken into account for (auto _br_port : bridge_ports) { auto br_port_vlans = rtnl_link_bridge_get_port_vlan(_br_port); if (rtnl_link_get_ifindex(vxlan_link) == rtnl_link_get_ifindex(_br_port)) continue; if (br_port_vlans == nullptr) continue; if (!is_vid_set(vid, br_port_vlans->vlan_bitmap)) continue; bool untagged = is_vid_set(vid, br_port_vlans->untagged_bitmap); int ifindex = rtnl_link_get_ifindex(_br_port); uint32_t pport_no = nl->get_port_id(ifindex); if (pport_no == 0) { LOG(WARNING) << __FUNCTION__ << ": ignoring unknown port " << OBJ_CAST(_br_port); continue; } rtnl_link *link = nl->get_link(rtnl_link_get_ifindex(_br_port), AF_UNSPEC); VLOG(2) << __FUNCTION__ << ": vid=" << vid << ", untagged=" << untagged << ", tunnel_id=" << tunnel_id << ", add=" << add << ", ifindex=" << ifindex << ", pport_no=" << pport_no << ", port: " << OBJ_CAST(_br_port); if (add) { std::string port_name = std::string(rtnl_link_get_name(_br_port)); // this is no longer a normal bridge interface thus we delete all the // bridging entries sw->l2_addr_remove_all_in_vlan(pport_no, vid); vxlan->create_access_port(_br_port, tunnel_id, port_name, pport_no, vid, untagged, nullptr); auto neighs = get_fdb_entries_of_port(_br_port, vid); for (auto n : neighs) { // ignore ll addr of bridge on slave if (nl_addr_cmp(rtnl_link_get_addr(bridge), rtnl_neigh_get_lladdr(n)) == 0) { continue; } VLOG(3) << ": needs to be updated " << OBJ_CAST(n); vxlan->add_l2_neigh(n, link, br_link); } } else { // delete access port and all bridging entries vxlan->delete_access_port(_br_port, pport_no, vid, true); // XXX FIXME check if we have to add the VLANs again (ingress/egress) } } }
int main(int argc, char *argv[]) { struct rtnl_addr *addr; struct nl_cache *link_cache, *addr_cache; sock = nl_cli_alloc_socket(); nl_cli_connect(sock, NETLINK_ROUTE); link_cache = nl_cli_link_alloc_cache(sock); addr_cache = nl_cli_addr_alloc_cache(sock); addr = nl_cli_addr_alloc(); for (;;) { int c, optidx = 0; enum { ARG_FAMILY = 257, ARG_LABEL = 258, ARG_YES, ARG_PEER, ARG_SCOPE, ARG_BROADCAST, ARG_PREFERRED, ARG_VALID, }; static struct option long_opts[] = { { "interactive", 0, 0, 'i' }, { "yes", 0, 0, ARG_YES }, { "quiet", 0, 0, 'q' }, { "help", 0, 0, 'h' }, { "version", 0, 0, 'v' }, { "local", 1, 0, 'a' }, { "dev", 1, 0, 'd' }, { "family", 1, 0, ARG_FAMILY }, { "label", 1, 0, ARG_LABEL }, { "peer", 1, 0, ARG_PEER }, { "scope", 1, 0, ARG_SCOPE }, { "broadcast", 1, 0, ARG_BROADCAST }, { "preferred", 1, 0, ARG_PREFERRED }, { "valid", 1, 0, ARG_VALID }, { 0, 0, 0, 0 } }; c = getopt_long(argc, argv, "iqhva:d:", long_opts, &optidx); if (c == -1) break; switch (c) { case 'i': interactive = 1; break; case ARG_YES: default_yes = 1; break; case 'q': quiet = 1; break; case 'h': print_usage(); break; case 'v': nl_cli_print_version(); break; case 'a': nl_cli_addr_parse_local(addr, optarg); break; case 'd': nl_cli_addr_parse_dev(addr, link_cache, optarg); break; case ARG_FAMILY: nl_cli_addr_parse_family(addr, optarg); break; case ARG_LABEL: nl_cli_addr_parse_label(addr, optarg); break; case ARG_PEER: nl_cli_addr_parse_peer(addr, optarg); break; case ARG_SCOPE: nl_cli_addr_parse_scope(addr, optarg); break; case ARG_BROADCAST: nl_cli_addr_parse_broadcast(addr, optarg); break; case ARG_PREFERRED: nl_cli_addr_parse_preferred(addr, optarg); break; case ARG_VALID: nl_cli_addr_parse_valid(addr, optarg); break; } } nl_cache_foreach_filter(addr_cache, OBJ_CAST(addr), delete_cb, NULL); if (!quiet) printf("Deleted %d addresses\n", deleted); return 0; }
int main(int argc, char *argv[]) { struct nl_sock *sock; struct rtnl_cls *cls; struct rtnl_tc *tc; struct nl_cache *link_cache; struct nl_dump_params dp = { .dp_type = NL_DUMP_DETAILS, .dp_fd = stdout, }; struct nl_cli_tc_module *tm; struct rtnl_tc_ops *ops; int err, flags = NLM_F_CREATE | NLM_F_EXCL; char *kind, *id = NULL; sock = nl_cli_alloc_socket(); nl_cli_connect(sock, NETLINK_ROUTE); link_cache = nl_cli_link_alloc_cache(sock); cls = nl_cli_cls_alloc(); tc = (struct rtnl_tc *) cls; for (;;) { int c, optidx = 0; enum { ARG_UPDATE = 257, ARG_UPDATE_ONLY = 258, ARG_MTU, ARG_MPU, ARG_OVERHEAD, ARG_LINKTYPE, ARG_PROTO, ARG_PRIO, }; static struct option long_opts[] = { { "quiet", 0, 0, 'q' }, { "help", 0, 0, 'h' }, { "version", 0, 0, 'v' }, { "dev", 1, 0, 'd' }, { "parent", 1, 0, 'p' }, { "id", 1, 0, 'i' }, { "proto", 1, 0, ARG_PROTO }, { "prio", 1, 0, ARG_PRIO }, { "update", 0, 0, ARG_UPDATE }, { "update-only", 0, 0, ARG_UPDATE_ONLY }, { "mtu", 1, 0, ARG_MTU }, { "mpu", 1, 0, ARG_MPU }, { "overhead", 1, 0, ARG_OVERHEAD }, { "linktype", 1, 0, ARG_LINKTYPE }, { 0, 0, 0, 0 } }; c = getopt_long(argc, argv, "+qhvd:p:i:", long_opts, &optidx); if (c == -1) break; switch (c) { case 'q': quiet = 1; break; case 'h': print_usage(); break; case 'v': nl_cli_print_version(); break; case 'd': nl_cli_tc_parse_dev(tc, link_cache, optarg); break; case 'p': nl_cli_tc_parse_parent(tc, optarg); break; case 'i': id = strdup(optarg); break; case ARG_UPDATE: flags = NLM_F_CREATE; break; case ARG_UPDATE_ONLY: flags = 0; break; case ARG_MTU: nl_cli_tc_parse_mtu(tc, optarg); break; case ARG_MPU: nl_cli_tc_parse_mpu(tc, optarg); break; case ARG_OVERHEAD: nl_cli_tc_parse_overhead(tc, optarg); break; case ARG_LINKTYPE: nl_cli_tc_parse_linktype(tc, optarg); break; case ARG_PROTO: nl_cli_cls_parse_proto(cls, optarg); break; case ARG_PRIO: rtnl_cls_set_prio(cls, nl_cli_parse_u32(optarg)); break; } } if (optind >= argc) print_usage(); if (!rtnl_tc_get_ifindex(tc)) nl_cli_fatal(EINVAL, "You must specify a network device (--dev=XXX)"); if (!rtnl_tc_get_parent(tc)) nl_cli_fatal(EINVAL, "You must specify a parent (--parent=XXX)"); if (id) { nl_cli_tc_parse_handle(tc, id, 1); free(id); } kind = argv[optind++]; rtnl_tc_set_kind(tc, kind); if (!(ops = rtnl_tc_get_ops(tc))) nl_cli_fatal(ENOENT, "Unknown classifier \"%s\".", kind); if (!(tm = nl_cli_tc_lookup(ops))) nl_cli_fatal(ENOTSUP, "Classifier type \"%s\" not supported.", kind); tm->tm_parse_argv(tc, argc, argv); if (!quiet) { printf("Adding "); nl_object_dump(OBJ_CAST(cls), &dp); } if ((err = rtnl_cls_add(sock, cls, flags)) < 0) nl_cli_fatal(EINVAL, "Unable to add classifier: %s", nl_geterror(err)); return 0; }
int main(int argc, char *argv[]) { struct nl_sock *sock; struct nl_dect_cluster *cl; struct nl_dect_ari *pari; struct nl_dump_params params = { .dp_type = NL_DUMP_LINE, .dp_fd = stdout, }; int err; sock = nl_cli_alloc_socket(); nl_cli_connect(sock, NETLINK_DECT); cl = nl_dect_cluster_alloc(); pari = (void *)nl_dect_cluster_get_pari(cl); for (;;) { int c, optidx = 0; enum { ARG_NAME = 257, ARG_MODE, ARG_EMC, ARG_FPN, }; static struct option long_opts[] = { { "name", 1, 0, ARG_NAME }, { "mode", 1, 0, ARG_MODE }, { "emc", 1, 0, ARG_EMC }, { "fpn", 1, 0, ARG_FPN }, { 0, 0, 0, 0 } }; c = getopt_long(argc, argv, "qhvd:n:t:", long_opts, &optidx); if (c == -1) break; switch (c) { case 'v': nl_cli_print_version(); break; case ARG_NAME: nl_dect_cluster_set_name(cl, strdup(optarg)); break; case ARG_MODE: nl_dect_cluster_set_mode(cl, atoi(optarg)); break; case ARG_EMC: nl_dect_ari_set_emc(pari, strtoul(optarg, NULL, 16)); break; case ARG_FPN: nl_dect_ari_set_fpn(pari, strtoul(optarg, NULL, 16)); break; } } err = nl_dect_cluster_delete(sock, cl, 0); if (err < 0) nl_cli_fatal(err, "Unable to delete cluster: %s", nl_geterror(err)); printf("Deleted: "); nl_object_dump(OBJ_CAST(cl), ¶ms); return 0; }
int main(int argc, char *argv[]) { struct nl_cache *link_cache, *route_cache; struct rtnl_route *route; int nf = 0; sock = nl_cli_alloc_socket(); nl_cli_connect(sock, NETLINK_ROUTE); link_cache = nl_cli_link_alloc_cache(sock); route_cache = nl_cli_route_alloc_cache(sock, 0); route = nl_cli_route_alloc(); for (;;) { int c, optidx = 0; enum { ARG_FAMILY = 257, ARG_SRC = 258, ARG_IIF, ARG_PREF_SRC, ARG_METRICS, ARG_PRIORITY, ARG_SCOPE, ARG_PROTOCOL, ARG_TYPE, ARG_YES, }; static struct option long_opts[] = { { "interactive", 0, 0, 'i' }, { "yes", 0, 0, ARG_YES }, { "quiet", 0, 0, 'q' }, { "help", 0, 0, 'h' }, { "version", 0, 0, 'v' }, { "dst", 1, 0, 'd' }, { "nexthop", 1, 0, 'n' }, { "table", 1, 0, 't' }, { "family", 1, 0, ARG_FAMILY }, { "src", 1, 0, ARG_SRC }, { "iif", 1, 0, ARG_IIF }, { "pref-src", 1, 0, ARG_PREF_SRC }, { "metrics", 1, 0, ARG_METRICS }, { "priority", 1, 0, ARG_PRIORITY }, { "scope", 1, 0, ARG_SCOPE }, { "protocol", 1, 0, ARG_PROTOCOL }, { "type", 1, 0, ARG_TYPE }, { 0, 0, 0, 0 } }; c = getopt_long(argc, argv, "iqhvd:n:t:", long_opts, &optidx); if (c == -1) break; switch (c) { case 'i': interactive = 1; break; case ARG_YES: default_yes = 1; break; case 'q': quiet = 1; break; case 'h': print_usage(); break; case 'v': print_version(); break; case 'd': nf++; nl_cli_route_parse_dst(route, optarg); break; case 'n': nf++; nl_cli_route_parse_nexthop(route, optarg, link_cache); break; case 't': nf++; nl_cli_route_parse_table(route, optarg); break; case ARG_FAMILY: nf++; nl_cli_route_parse_family(route, optarg); break; case ARG_SRC: nf++; nl_cli_route_parse_src(route, optarg); break; case ARG_IIF: nf++; nl_cli_route_parse_iif(route, optarg, link_cache); break; case ARG_PREF_SRC: nf++; nl_cli_route_parse_pref_src(route, optarg); break; case ARG_METRICS: nf++; nl_cli_route_parse_metric(route, optarg); break; case ARG_PRIORITY: nf++; nl_cli_route_parse_prio(route, optarg); break; case ARG_SCOPE: nf++; nl_cli_route_parse_scope(route, optarg); break; case ARG_PROTOCOL: nf++; nl_cli_route_parse_protocol(route, optarg); break; case ARG_TYPE: nf++; nl_cli_route_parse_type(route, optarg); break; } } if (nf == 0 && !interactive && !default_yes) { fprintf(stderr, "You attempted to delete all routes in " "non-interactive mode, aborting.\n"); exit(0); } nl_cache_foreach_filter(route_cache, OBJ_CAST(route), delete_cb, NULL); if (!quiet) printf("Deleted %d routes\n", deleted); return 0; }
int main(int argc, char *argv[]) { struct nl_sock *sock; struct nfnl_ct *ct; struct nl_dump_params params = { .dp_type = NL_DUMP_LINE, .dp_fd = stdout, }; int err, nlflags = NLM_F_CREATE; ct = nl_cli_ct_alloc(); for (;;) { int c, optidx = 0; enum { ARG_ORIG_SRC = 257, ARG_ORIG_SPORT = 258, ARG_ORIG_DST, ARG_ORIG_DPORT, ARG_REPLY_SRC, ARG_REPLY_SPORT, ARG_REPLY_DST, ARG_REPLY_DPORT, ARG_MARK, ARG_TIMEOUT, ARG_STATUS, ARG_ZONE, }; static struct option long_opts[] = { { "quiet", 0, 0, 'q' }, { "help", 0, 0, 'h' }, { "version", 0, 0, 'v' }, { "proto", 1, 0, 'p' }, { "orig-src", 1, 0, ARG_ORIG_SRC }, { "orig-sport", 1, 0, ARG_ORIG_SPORT }, { "orig-dst", 1, 0, ARG_ORIG_DST }, { "orig-dport", 1, 0, ARG_ORIG_DPORT }, { "reply-src", 1, 0, ARG_REPLY_SRC }, { "reply-sport", 1, 0, ARG_REPLY_SPORT }, { "reply-dst", 1, 0, ARG_REPLY_DST }, { "reply-dport", 1, 0, ARG_REPLY_DPORT }, { "family", 1, 0, 'F' }, { "mark", 1, 0, ARG_MARK }, { "timeout", 1, 0, ARG_TIMEOUT }, { "status", 1, 0, ARG_STATUS }, { "zone", 1, 0, ARG_ZONE }, { 0, 0, 0, 0 } }; c = getopt_long(argc, argv, "46q:hv:p:F:", long_opts, &optidx); if (c == -1) break; switch (c) { case '?': exit(NLE_INVAL); case 'q': quiet = 1; break; case '4': nfnl_ct_set_family(ct, AF_INET); break; case '6': nfnl_ct_set_family(ct, AF_INET6); break; case 'h': print_usage(); break; case 'v': nl_cli_print_version(); break; case 'p': nl_cli_ct_parse_protocol(ct, optarg); break; case ARG_ORIG_SRC: nl_cli_ct_parse_src(ct, 0, optarg); break; case ARG_ORIG_SPORT: nl_cli_ct_parse_src_port(ct, 0, optarg); break; case ARG_ORIG_DST: nl_cli_ct_parse_dst(ct, 0, optarg); break; case ARG_ORIG_DPORT: nl_cli_ct_parse_dst_port(ct, 0, optarg); break; case ARG_REPLY_SRC: nl_cli_ct_parse_src(ct, 1, optarg); break; case ARG_REPLY_SPORT: nl_cli_ct_parse_src_port(ct, 1, optarg); break; case ARG_REPLY_DST: nl_cli_ct_parse_dst(ct, 1, optarg); break; case ARG_REPLY_DPORT: nl_cli_ct_parse_dst_port(ct, 1, optarg); break; case 'F': nl_cli_ct_parse_family(ct, optarg); break; case ARG_MARK: nl_cli_ct_parse_mark(ct, optarg); break; case ARG_TIMEOUT: nl_cli_ct_parse_timeout(ct, optarg); break; case ARG_STATUS: nl_cli_ct_parse_status(ct, optarg); break; case ARG_ZONE: nl_cli_ct_parse_zone(ct, optarg); break; } } if (!quiet) { printf("Adding "); nl_object_dump(OBJ_CAST(ct), ¶ms); } sock = nl_cli_alloc_socket(); nl_cli_connect(sock, NETLINK_NETFILTER); if ((err = nfnl_ct_add(sock, ct, nlflags)) < 0) nl_cli_fatal(err, "Unable to add conntrack: %s", nl_geterror(err)); if (!quiet) { printf("Added "); nl_object_dump(OBJ_CAST(ct), ¶ms); } return 0; }
int main(int argc, char *argv[]) { struct nl_sock *sock; struct nl_cache *exp_cache; struct nfnl_exp *exp; struct nl_dump_params params = { .dp_type = NL_DUMP_LINE, .dp_fd = stdout, }; exp = nl_cli_exp_alloc(); for (;;) { int c, optidx = 0; enum { ARG_MARK = 270, ARG_TCP_STATE = 271, ARG_EXPECT_PROTO, ARG_EXPECT_SRC, ARG_EXPECT_SPORT, ARG_EXPECT_DST, ARG_EXPECT_DPORT, ARG_MASTER_PROTO, ARG_MASTER_SRC, ARG_MASTER_SPORT, ARG_MASTER_DST, ARG_MASTER_DPORT, ARG_TIMEOUT, ARG_HELPER_NAME, ARG_FLAGS, }; static struct option long_opts[] = { { "format", 1, 0, 'f' }, { "help", 0, 0, 'h' }, { "version", 0, 0, 'v' }, { "id", 1, 0, 'i' }, { "expect-proto", 1, 0, ARG_EXPECT_PROTO }, { "expect-src", 1, 0, ARG_EXPECT_SRC }, { "expect-sport", 1, 0, ARG_EXPECT_SPORT }, { "expect-dst", 1, 0, ARG_EXPECT_DST }, { "expect-dport", 1, 0, ARG_EXPECT_DPORT }, { "master-proto", 1, 0, ARG_MASTER_PROTO }, { "master-src", 1, 0, ARG_MASTER_SRC }, { "master-sport", 1, 0, ARG_MASTER_SPORT }, { "master-dst", 1, 0, ARG_MASTER_DST }, { "master-dport", 1, 0, ARG_MASTER_DPORT }, { "family", 1, 0, 'F' }, { "timeout", 1, 0, ARG_TIMEOUT }, { "helper", 1, 0, ARG_HELPER_NAME }, { "flags", 1, 0, ARG_FLAGS}, { 0, 0, 0, 0 } }; c = getopt_long(argc, argv, "46f:hvi:p:F:", long_opts, &optidx); if (c == -1) break; switch (c) { case '?': exit(NLE_INVAL); case '4': nfnl_exp_set_family(exp, AF_INET); break; case '6': nfnl_exp_set_family(exp, AF_INET6); break; case 'f': params.dp_type = nl_cli_parse_dumptype(optarg); break; case 'h': print_usage(); break; case 'v': nl_cli_print_version(); break; case 'i': nl_cli_exp_parse_id(exp, optarg); break; case ARG_EXPECT_PROTO: nl_cli_exp_parse_l4protonum(exp, NFNL_EXP_TUPLE_EXPECT, optarg); break; case ARG_EXPECT_SRC: nl_cli_exp_parse_src(exp, NFNL_EXP_TUPLE_EXPECT, optarg); break; case ARG_EXPECT_SPORT: nl_cli_exp_parse_src_port(exp, NFNL_EXP_TUPLE_EXPECT, optarg); break; case ARG_EXPECT_DST: nl_cli_exp_parse_dst(exp, NFNL_EXP_TUPLE_EXPECT, optarg); break; case ARG_EXPECT_DPORT: nl_cli_exp_parse_dst_port(exp, NFNL_EXP_TUPLE_EXPECT, optarg); break; case ARG_MASTER_PROTO: nl_cli_exp_parse_l4protonum(exp, NFNL_EXP_TUPLE_MASTER, optarg); break; case ARG_MASTER_SRC: nl_cli_exp_parse_src(exp, NFNL_EXP_TUPLE_MASTER, optarg); break; case ARG_MASTER_SPORT: nl_cli_exp_parse_src_port(exp, NFNL_EXP_TUPLE_MASTER, optarg); break; case ARG_MASTER_DST: nl_cli_exp_parse_dst(exp, NFNL_EXP_TUPLE_MASTER, optarg); break; case ARG_MASTER_DPORT: nl_cli_exp_parse_dst_port(exp, NFNL_EXP_TUPLE_MASTER, optarg); break; case 'F': nl_cli_exp_parse_family(exp, optarg); break; case ARG_TIMEOUT: nl_cli_exp_parse_timeout(exp, optarg); break; case ARG_HELPER_NAME: nl_cli_exp_parse_helper_name(exp, optarg); break; case ARG_FLAGS: nl_cli_exp_parse_flags(exp, optarg); break; } } sock = nl_cli_alloc_socket(); nl_cli_connect(sock, NETLINK_NETFILTER); exp_cache = nl_cli_exp_alloc_cache(sock); nl_cache_dump_filter(exp_cache, ¶ms, OBJ_CAST(exp)); return 0; }
static void nl_ihandler_cb(struct incident *i, void *ctx) { g_debug("%s i %p ctx %p", __PRETTY_FUNCTION__, i, ctx); struct connection *con; incident_value_con_get(i, "con", &con); char *remote = con->remote.ip_string; char *local = con->local.ip_string; char *prefix = "::ffff:"; if( strncmp(local, prefix, strlen(prefix)) == 0) local += strlen(prefix); if( strncmp(remote, prefix, strlen(prefix)) == 0) remote += strlen(prefix); int ifindex; int err; { g_debug("local addr %s remote addr %s", local, remote); struct rtnl_addr *addr = rtnl_addr_alloc(); struct nl_addr *a; if ( ( err = nl_addr_parse(local, AF_UNSPEC, &a)) != 0 ) g_critical("could not parse addr %s (%s)", local, nl_geterror(err)); rtnl_addr_set_local(addr, a); nl_addr_put(a); struct rtnl_addr *res = NULL; nl_cache_foreach_filter(nl_runtime.addr_cache, OBJ_CAST(addr), cache_lookup_cb, &res); g_critical("LOCAL RTNL_ADDR %p", res); /* struct nl_dump_params params = { .dp_type = NL_DUMP_LINE, .dp_fd = stdout, }; nl_cache_dump_filter(nl_runtime.addr_cache, ¶ms, OBJ_CAST(addr)); */ ifindex = rtnl_addr_get_ifindex(res); } struct rtnl_neigh *res = NULL; { struct rtnl_neigh *neigh = rtnl_neigh_alloc(); rtnl_neigh_set_ifindex(neigh, ifindex); struct nl_addr *a; if ( ( err = nl_addr_parse(remote, AF_UNSPEC, &a)) != 0 ) g_critical("could not parse addr %s (%s)", remote, nl_geterror(err)); rtnl_neigh_set_dst(neigh, a); nl_addr_put(a); nl_cache_foreach_filter(nl_runtime.neigh_cache, OBJ_CAST(neigh), cache_lookup_cb, &res); } if( res ) { g_critical("GOT NEIGH %p", res); struct nl_addr *lladdr = rtnl_neigh_get_lladdr(res); char buf[123]; nl_addr2str(lladdr, buf, sizeof(buf)); g_critical("GOT NEIGH %s", buf); struct incident *i = incident_new("dionaea.module.nl.connection.info.mac"); incident_value_string_set(i, "mac", g_string_new(buf)); incident_value_con_set(i, "con", con); incident_report(i); incident_free(i); } }
int netem_get_params(char *iface, struct netem_params *params) { struct rtnl_link *link; struct rtnl_qdisc *filter_qdisc; struct rtnl_qdisc *found_qdisc = NULL; int err; int delay, jitter, loss; pthread_mutex_lock(&nl_sock_mutex); if ((err = nl_cache_refill(sock, link_cache)) < 0) { fprintf(stderr, "Unable to resync link cache: %s\n", nl_geterror(err)); goto cleanup; } if ((err = nl_cache_refill(sock, qdisc_cache)) < 0) { fprintf(stderr, "Unable to resync link cache: %s\n", nl_geterror(err)); goto cleanup; } /* filter link by name */ if ((link = rtnl_link_get_by_name(link_cache, iface)) == NULL) { fprintf(stderr, "unknown interface/link name.\n"); goto cleanup; } if (!(filter_qdisc = rtnl_qdisc_alloc())) { /* OOM error */ fprintf(stderr, "couldn't alloc qdisc\n"); goto cleanup_link; } rtnl_tc_set_link(TC_CAST(filter_qdisc), link); rtnl_tc_set_parent(TC_CAST(filter_qdisc), TC_H_ROOT); rtnl_tc_set_kind(TC_CAST(filter_qdisc), "netem"); found_qdisc = (struct rtnl_qdisc *)nl_cache_find( qdisc_cache, OBJ_CAST(filter_qdisc)); if (!found_qdisc) { /* The iface probably doesn't have a netem qdisc at startup. */ goto cleanup_filter_qdisc; } if (0 > (delay = rtnl_netem_get_delay(found_qdisc))) { fprintf(stderr, "couldn't get delay for iface: %s\n", iface); goto cleanup_qdisc; } params->delay = (double)delay / 1000; if (0 > (jitter = rtnl_netem_get_jitter(found_qdisc))) { fprintf(stderr, "couldn't get jitter for iface: %s\n", iface); goto cleanup_qdisc; } params->jitter = (double)jitter / 1000; if (0 > (loss = rtnl_netem_get_loss(found_qdisc))) { fprintf(stderr, "couldn't get loss for iface: %s\n", iface); goto cleanup_qdisc; } /* loss is specified in 10ths of a percent, ie. 1 ==> 0.1% */ params->loss = (int)(loss / (UINT_MAX / 1000)); rtnl_qdisc_put(found_qdisc); rtnl_qdisc_put(filter_qdisc); rtnl_link_put(link); pthread_mutex_unlock(&nl_sock_mutex); return 0; cleanup_qdisc: rtnl_qdisc_put(found_qdisc); cleanup_filter_qdisc: rtnl_qdisc_put(filter_qdisc); cleanup_link: rtnl_link_put(link); cleanup: pthread_mutex_unlock(&nl_sock_mutex); return -1; }
void link_destroy(struct rtnl_link *link) { if (link) nl_object_free(OBJ_CAST(link)); }
void nl_bridge::update_vlans(rtnl_link *old_link, rtnl_link *new_link) { assert(sw); assert(bridge); // already checked rtnl_link_bridge_vlan *old_br_vlan, *new_br_vlan; rtnl_link *_link; if (old_link == nullptr) { // link added old_br_vlan = &empty_br_vlan; new_br_vlan = rtnl_link_bridge_get_port_vlan(new_link); _link = nl->get_link(rtnl_link_get_ifindex(new_link), AF_UNSPEC); } else if (new_link == nullptr) { // link deleted old_br_vlan = rtnl_link_bridge_get_port_vlan(old_link); new_br_vlan = &empty_br_vlan; _link = nl->get_link(rtnl_link_get_ifindex(old_link), AF_UNSPEC); } else { // link updated old_br_vlan = rtnl_link_bridge_get_port_vlan(old_link); new_br_vlan = rtnl_link_bridge_get_port_vlan(new_link); _link = nl->get_link(rtnl_link_get_ifindex(new_link), AF_UNSPEC); } if (old_br_vlan == nullptr) { old_br_vlan = &empty_br_vlan; } if (new_br_vlan == nullptr) { new_br_vlan = &empty_br_vlan; } if (_link == nullptr) { // XXX FIXME in case a vxlan has been deleted the vxlan_domain and // vxlan_dom_bitmap need an update, maybe this can be handled already from // the link_deleted of the vxlan itself? LOG(WARNING) << __FUNCTION__ << ": could not get parent link of bridge interface. This " "case needs further checks if everything got already " "deleted."; return; } // check for vid changes if (br_vlan_equal(old_br_vlan, new_br_vlan)) { VLOG(2) << __FUNCTION__ << ": vlans did not change"; return; } link_type lt = get_link_type(_link); uint32_t pport_no = 0; uint32_t tunnel_id = -1; std::deque<rtnl_link *> bridge_ports; if (lt == LT_VXLAN) { assert(nl); nl->get_bridge_ports(rtnl_link_get_master(_link), &bridge_ports); if (vxlan->get_tunnel_id(_link, nullptr, &tunnel_id) != 0) { LOG(ERROR) << __FUNCTION__ << ": failed to get vni of link " << OBJ_CAST(_link); } } else { pport_no = nl->get_port_id(rtnl_link_get_ifindex(_link)); if (pport_no == 0) { LOG(ERROR) << __FUNCTION__ << ": invalid pport_no=0 of link: " << OBJ_CAST(_link); return; } } for (int k = 0; k < RTNL_LINK_BRIDGE_VLAN_BITMAP_LEN; k++) { int base_bit; uint32_t a = old_br_vlan->vlan_bitmap[k]; uint32_t b = new_br_vlan->vlan_bitmap[k]; uint32_t vlan_diff = a ^ b; #if 0 // untagged change not yet implemented uint32_t c = old_br_vlan->untagged_bitmap[k]; uint32_t d = new_br_vlan->untagged_bitmap[k]; uint32_t untagged_diff = c ^ d; #endif // 0 base_bit = k * 32; int i = -1; int done = 0; while (!done) { int j = find_next_bit(i, vlan_diff); if (j > 0) { // vlan added or removed int vid = j - 1 + base_bit; bool egress_untagged = false; // check if egress is untagged if (new_br_vlan->untagged_bitmap[k] & 1 << (j - 1)) { egress_untagged = true; #if 0 // untagged change not yet implemented // clear untagged_diff bit untagged_diff &= ~((uint32_t)1 << (j - 1)); #endif // 0 } if (new_br_vlan->vlan_bitmap[k] & 1 << (j - 1)) { // vlan added if (lt == LT_VXLAN) { // update vxlan domain if (!is_vid_set(vid, vxlan_dom_bitmap)) { VLOG(1) << __FUNCTION__ << ": new vxlan domain vid=" << vid << ", tunnel_id=" << tunnel_id; vxlan_domain.emplace(vid, tunnel_id); set_vid(vid, vxlan_dom_bitmap); } else { // XXX TODO check the map } // update all bridge ports to be access ports update_access_ports(_link, new_link ? new_link : old_link, vid, tunnel_id, bridge_ports, true); } else { assert(pport_no); if (is_vid_set(vid, vxlan_dom_bitmap)) { // configure as access port std::string port_name = std::string(rtnl_link_get_name(_link)); auto vxd_it = vxlan_domain.find(vid); if (vxd_it != vxlan_domain.end()) { vxlan->create_access_port((new_link) ? new_link : old_link, vxd_it->second, port_name, pport_no, vid, egress_untagged, nullptr); } else { LOG(FATAL) << __FUNCTION__ << ": should not happen, something is broken"; } } else { // normal vlan port VLOG(3) << __FUNCTION__ << ": add vid=" << vid << " on pport_no=" << pport_no << " link: " << OBJ_CAST(_link); sw->egress_bridge_port_vlan_add(pport_no, vid, egress_untagged); sw->ingress_port_vlan_add(pport_no, vid, new_br_vlan->pvid == vid); } } } else { // vlan removed if (lt == LT_VXLAN) { unset_vid(vid, vxlan_dom_bitmap); vxlan_domain.erase(vid); // update all bridge ports to be normal bridge ports update_access_ports(_link, new_link ? new_link : old_link, vid, tunnel_id, bridge_ports, false); } else { VLOG(3) << __FUNCTION__ << ": remove vid=" << vid << " on pport_no=" << pport_no << " link: " << OBJ_CAST(_link); sw->ingress_port_vlan_remove(pport_no, vid, old_br_vlan->pvid == vid); // delete all FM pointing to this group first sw->l2_addr_remove_all_in_vlan(pport_no, vid); std::unique_ptr<rtnl_neigh, decltype(&rtnl_neigh_put)> filter( rtnl_neigh_alloc(), rtnl_neigh_put); rtnl_neigh_set_ifindex(filter.get(), rtnl_link_get_ifindex(bridge)); rtnl_neigh_set_master(filter.get(), rtnl_link_get_master(bridge)); rtnl_neigh_set_family(filter.get(), AF_BRIDGE); rtnl_neigh_set_vlan(filter.get(), vid); rtnl_neigh_set_flags(filter.get(), NTF_MASTER | NTF_EXT_LEARNED); rtnl_neigh_set_state(filter.get(), NUD_REACHABLE); nl_cache_foreach_filter(l2_cache.get(), OBJ_CAST(filter.get()), [](struct nl_object *o, void *arg) { VLOG(3) << "l2_cache remove object " << o; nl_cache_remove(o); }, nullptr); sw->egress_bridge_port_vlan_remove(pport_no, vid); } } i = j; } else { done = 1; } } #if 0 // not yet implemented the update done = 0; i = -1; while (!done) { // vlan is existing, but swapping egress tagged/untagged int j = find_next_bit(i, untagged_diff); if (j > 0) { // egress untagged changed int vid = j - 1 + base_bit; bool egress_untagged = false; // check if egress is untagged if (new_br_vlan->untagged_bitmap[k] & 1 << (j-1)) { egress_untagged = true; } // XXX implement update fm_driver.update_port_vid_egress(devname, vid, egress_untagged); i = j; } else { done = 1; } } #endif } }