diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/bfd.c | 3 | ||||
| -rw-r--r-- | lib/command.c | 5 | ||||
| -rw-r--r-- | lib/elf_py.c | 120 | ||||
| -rw-r--r-- | lib/if.c | 23 | ||||
| -rw-r--r-- | lib/log.c | 10 | ||||
| -rw-r--r-- | lib/routemap.c | 26 | ||||
| -rw-r--r-- | lib/routemap.h | 3 | ||||
| -rw-r--r-- | lib/routemap_cli.c | 71 | ||||
| -rw-r--r-- | lib/routemap_northbound.c | 31 | ||||
| -rw-r--r-- | lib/zclient.c | 71 | ||||
| -rw-r--r-- | lib/zclient.h | 33 |
11 files changed, 342 insertions, 54 deletions
@@ -988,6 +988,9 @@ void bfd_sess_show(struct vty *vty, struct json_object *json, json_object *json_bfd = NULL; char time_buf[64]; + if (!bsp) + return; + /* Show type. */ if (json) { json_bfd = json_object_new_object(); diff --git a/lib/command.c b/lib/command.c index 770e2fc5ac..d2798b5002 100644 --- a/lib/command.c +++ b/lib/command.c @@ -2226,18 +2226,19 @@ DEFUN (no_banner_motd, DEFUN(find, find_cmd, - "find REGEX", + "find REGEX...", "Find CLI command matching a regular expression\n" "Search pattern (POSIX regex)\n") { - char *pattern = argv[1]->arg; const struct cmd_node *node; const struct cmd_element *cli; vector clis; regex_t exp = {}; + char *pattern = argv_concat(argv, argc, 1); int cr = regcomp(&exp, pattern, REG_NOSUB | REG_EXTENDED); + XFREE(MTYPE_TMP, pattern); if (cr != 0) { switch (cr) { diff --git a/lib/elf_py.c b/lib/elf_py.c index d26e443b82..b47aa3d795 100644 --- a/lib/elf_py.c +++ b/lib/elf_py.c @@ -1032,7 +1032,7 @@ static char *elfdata_strptr(Elf_Data *data, size_t offset) static void elffile_add_dynreloc(struct elffile *w, Elf_Data *reldata, size_t entries, Elf_Data *symdata, - Elf_Data *strdata) + Elf_Data *strdata, Elf_Type typ) { size_t i; @@ -1041,12 +1041,59 @@ static void elffile_add_dynreloc(struct elffile *w, Elf_Data *reldata, size_t symidx; GElf_Rela *rela; GElf_Sym *sym; + GElf_Addr rel_offs = 0; relw = (struct elfreloc *)typeobj_elfreloc.tp_alloc( &typeobj_elfreloc, 0); relw->ef = w; - rela = relw->rela = gelf_getrela(reldata, i, &relw->_rela); + if (typ == ELF_T_REL) { + GElf_Rel _rel, *rel; + GElf_Addr offs; + + rel = gelf_getrel(reldata, i, &_rel); + relw->rela = &relw->_rela; + relw->rela->r_offset = rel->r_offset; + relw->rela->r_info = rel->r_info; + relw->rela->r_addend = 0; + relw->relative = true; + + /* REL uses the pointer contents itself instead of the + * RELA addend field :( ... theoretically this could + * be some weird platform specific encoding, but since + * we only care about data relocations it should + * always be a pointer... + */ + if (elffile_virt2file(w, rel->r_offset, &offs)) { + Elf_Data *ptr, *conv; + GElf_Addr tmp; + Elf_Data mem = { + .d_buf = (void *)&tmp, + .d_type = ELF_T_ADDR, + .d_version = EV_CURRENT, + .d_size = sizeof(tmp), + .d_off = 0, + .d_align = 0, + }; + + ptr = elf_getdata_rawchunk(w->elf, offs, + w->elfclass / 8, + ELF_T_ADDR); + + conv = gelf_xlatetom(w->elf, &mem, ptr, + w->mmap[EI_DATA]); + if (conv) { + memcpy(&rel_offs, conv->d_buf, + conv->d_size); + + relw->relative = false; + relw->rela->r_addend = rel_offs; + } + } + } else + relw->rela = gelf_getrela(reldata, i, &relw->_rela); + + rela = relw->rela; symidx = relw->symidx = GELF_R_SYM(rela->r_info); sym = relw->sym = gelf_getsym(symdata, symidx, &relw->_sym); if (sym) { @@ -1062,9 +1109,16 @@ static void elffile_add_dynreloc(struct elffile *w, Elf_Data *reldata, relw->st_value = 0; } - debugf("dynreloc @ %016llx sym %5llu %016llx %s\n", - (long long)rela->r_offset, (unsigned long long)symidx, - (long long)rela->r_addend, relw->symname); + if (typ == ELF_T_RELA) + debugf("dynrela @ %016llx sym %5llu %016llx %s\n", + (long long)rela->r_offset, + (unsigned long long)symidx, + (long long)rela->r_addend, relw->symname); + else + debugf("dynrel @ %016llx sym %5llu (%016llx) %s\n", + (long long)rela->r_offset, + (unsigned long long)symidx, + (unsigned long long)rel_offs, relw->symname); elfrelocs_add(&w->dynrelocs, relw); } @@ -1166,8 +1220,10 @@ static PyObject *elffile_load(PyTypeObject *type, PyObject *args, Elf_Data *dyndata = elf_getdata_rawchunk(w->elf, phdr->p_offset, phdr->p_filesz, ELF_T_DYN); - GElf_Addr dynrela = 0, symtab = 0, strtab = 0; - size_t dynrelasz = 0, dynrelaent = 0, strsz = 0; + GElf_Addr dynrela = 0, dynrel = 0, symtab = 0, strtab = 0; + size_t dynrelasz = 0, dynrelaent = 0; + size_t dynrelsz = 0, dynrelent = 0; + size_t strsz = 0; GElf_Dyn _dyn, *dyn; for (size_t j = 0;; j++) { @@ -1198,16 +1254,20 @@ static PyObject *elffile_load(PyTypeObject *type, PyObject *args, dynrelaent = dyn->d_un.d_val; break; + case DT_REL: + dynrel = dyn->d_un.d_ptr; + break; case DT_RELSZ: - if (dyn->d_un.d_val) - fprintf(stderr, - "WARNING: ignoring non-empty DT_REL!\n"); + dynrelsz = dyn->d_un.d_val; + break; + case DT_RELENT: + dynrelent = dyn->d_un.d_val; break; } } GElf_Addr offset; - Elf_Data *symdata = NULL, *strdata = NULL, *reladata = NULL; + Elf_Data *symdata = NULL, *strdata = NULL; if (elffile_virt2file(w, symtab, &offset)) symdata = elf_getdata_rawchunk(w->elf, offset, @@ -1217,19 +1277,37 @@ static PyObject *elffile_load(PyTypeObject *type, PyObject *args, strdata = elf_getdata_rawchunk(w->elf, offset, strsz, ELF_T_BYTE); - if (!dynrela || !dynrelasz || !dynrelaent) - continue; + size_t c; - if (!elffile_virt2file(w, dynrela, &offset)) - continue; + if (dynrela && dynrelasz && dynrelaent + && elffile_virt2file(w, dynrela, &offset)) { + Elf_Data *reladata = NULL; - debugf("dynrela @%llx/%llx+%llx\n", (long long)dynrela, - (long long)offset, (long long)dynrelasz); + debugf("dynrela @%llx/%llx+%llx\n", (long long)dynrela, + (long long)offset, (long long)dynrelasz); - reladata = elf_getdata_rawchunk(w->elf, offset, dynrelasz, - ELF_T_RELA); - elffile_add_dynreloc(w, reladata, dynrelasz / dynrelaent, - symdata, strdata); + reladata = elf_getdata_rawchunk(w->elf, offset, + dynrelasz, ELF_T_RELA); + + c = dynrelasz / dynrelaent; + elffile_add_dynreloc(w, reladata, c, symdata, strdata, + ELF_T_RELA); + } + + if (dynrel && dynrelsz && dynrelent + && elffile_virt2file(w, dynrel, &offset)) { + Elf_Data *reldata = NULL; + + debugf("dynrel @%llx/%llx+%llx\n", (long long)dynrel, + (long long)offset, (long long)dynrelsz); + + reldata = elf_getdata_rawchunk(w->elf, offset, dynrelsz, + ELF_T_REL); + + c = dynrelsz / dynrelent; + elffile_add_dynreloc(w, reldata, c, symdata, strdata, + ELF_T_REL); + } } #endif @@ -1056,15 +1056,30 @@ struct connected *connected_get_linklocal(struct interface *ifp) void if_terminate(struct vrf *vrf) { struct interface *ifp; + bool delete; + + /* + * If the default VRF is being terminated or has + * already been terminated it means that + * the program is shutting down and we need to + * delete all the interfaces. Otherwise, we only + * need to move VRF's interfaces to the default VRF. + */ + delete = vrf_is_backend_netns() || vrf->vrf_id == VRF_DEFAULT + || !vrf_lookup_by_id(VRF_DEFAULT); while (!RB_EMPTY(if_name_head, &vrf->ifaces_by_name)) { ifp = RB_ROOT(if_name_head, &vrf->ifaces_by_name); - if (ifp->node) { - ifp->node->info = NULL; - route_unlock_node(ifp->node); + if (delete) { + if (ifp->node) { + ifp->node->info = NULL; + route_unlock_node(ifp->node); + } + if_delete(&ifp); + } else { + if_update_to_new_vrf(ifp, VRF_DEFAULT); } - if_delete(&ifp); } } @@ -464,7 +464,15 @@ static const struct zebra_desc_table command_types[] = { DESC_ENTRY(ZEBRA_ROUTE_NOTIFY_REQUEST), DESC_ENTRY(ZEBRA_CLIENT_CLOSE_NOTIFY), DESC_ENTRY(ZEBRA_EVPN_REMOTE_NH_ADD), - DESC_ENTRY(ZEBRA_EVPN_REMOTE_NH_DEL)}; + DESC_ENTRY(ZEBRA_EVPN_REMOTE_NH_DEL), + DESC_ENTRY(ZEBRA_NHRP_NEIGH_ADDED), + DESC_ENTRY(ZEBRA_NHRP_NEIGH_REMOVED), + DESC_ENTRY(ZEBRA_NHRP_NEIGH_GET), + DESC_ENTRY(ZEBRA_NHRP_NEIGH_REGISTER), + DESC_ENTRY(ZEBRA_NHRP_NEIGH_UNREGISTER), + DESC_ENTRY(ZEBRA_NEIGH_IP_ADD), + DESC_ENTRY(ZEBRA_NEIGH_IP_DEL), + DESC_ENTRY(ZEBRA_CONFIGURE_ARP)}; #undef DESC_ENTRY static const struct zebra_desc_table unknown = {0, "unknown", '?'}; diff --git a/lib/routemap.c b/lib/routemap.c index 33c65ac333..b2cb299fd3 100644 --- a/lib/routemap.c +++ b/lib/routemap.c @@ -2906,29 +2906,6 @@ void route_map_notify_dependencies(const char *affected_name, } /* VTY related functions. */ -DEFUN(no_routemap_optimization, no_routemap_optimization_cmd, - "no route-map optimization", - NO_STR - "route-map\n" - "optimization\n") -{ - VTY_DECLVAR_CONTEXT(route_map_index, index); - - index->map->optimization_disabled = true; - return CMD_SUCCESS; -} - -DEFUN(routemap_optimization, routemap_optimization_cmd, - "route-map optimization", - "route-map\n" - "optimization\n") -{ - VTY_DECLVAR_CONTEXT(route_map_index, index); - - index->map->optimization_disabled = false; - return CMD_SUCCESS; -} - static void clear_route_map_helper(struct route_map *map) { struct route_map_index *index; @@ -3241,8 +3218,5 @@ void route_map_init(void) install_element(ENABLE_NODE, &debug_rmap_cmd); install_element(ENABLE_NODE, &no_debug_rmap_cmd); - install_element(RMAP_NODE, &routemap_optimization_cmd); - install_element(RMAP_NODE, &no_routemap_optimization_cmd); - install_element(ENABLE_NODE, &show_route_map_pfx_tbl_cmd); } diff --git a/lib/routemap.h b/lib/routemap.h index 6385193bbf..5b6b64eaeb 100644 --- a/lib/routemap.h +++ b/lib/routemap.h @@ -902,6 +902,9 @@ extern void route_map_call_show(struct vty *vty, struct lyd_node *dnode, extern void route_map_description_show(struct vty *vty, struct lyd_node *dnode, bool show_defaults); +extern void route_map_optimization_disabled_show(struct vty *vty, + struct lyd_node *dnode, + bool show_defaults); extern void route_map_cli_init(void); #ifdef __cplusplus diff --git a/lib/routemap_cli.c b/lib/routemap_cli.c index 9a53c11a4c..e11b9eea74 100644 --- a/lib/routemap_cli.c +++ b/lib/routemap_cli.c @@ -1396,6 +1396,74 @@ void route_map_description_show(struct vty *vty, struct lyd_node *dnode, vty_out(vty, " description %s\n", yang_dnode_get_string(dnode, NULL)); } +DEFPY_YANG( + route_map_optimization, route_map_optimization_cmd, + "[no] route-map WORD$name optimization", + NO_STR + ROUTE_MAP_CMD_STR + "Configure route-map optimization\n") +{ + char xpath[XPATH_MAXLEN]; + + snprintf(xpath, sizeof(xpath), + "/frr-route-map:lib/route-map[name='%s']", name); + nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); + + snprintf( + xpath, sizeof(xpath), + "/frr-route-map:lib/route-map[name='%s']/optimization-disabled", + name); + nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, no ? "true" : "false"); + + return nb_cli_apply_changes(vty, NULL); +} + +void route_map_optimization_disabled_show(struct vty *vty, + struct lyd_node *dnode, + bool show_defaults) +{ + const char *name = yang_dnode_get_string(dnode, "../name"); + const bool disabled = yang_dnode_get_bool(dnode, NULL); + + vty_out(vty, "%sroute-map %s optimization\n", disabled ? "no " : "", + name); +} + +#if CONFDATE > 20220409 +CPP_NOTICE("Time to remove old route-map optimization command") +#endif + +DEFPY_HIDDEN( + routemap_optimization, routemap_optimization_cmd, + "[no] route-map optimization", + NO_STR + "route-map\n" + "optimization\n") +{ + const struct lyd_node *rmi_dnode; + const char *rm_name; + char xpath[XPATH_MAXLEN]; + + vty_out(vty, + "%% This command is deprecated. Please, use `route-map NAME optimization` from the config node.\n"); + + rmi_dnode = + yang_dnode_get(vty->candidate_config->dnode, VTY_CURR_XPATH); + if (!rmi_dnode) { + vty_out(vty, "%% Failed to get RMI dnode in candidate DB\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + rm_name = yang_dnode_get_string(rmi_dnode, "../name"); + + snprintf( + xpath, sizeof(xpath), + "/frr-route-map:lib/route-map[name='%s']/optimization-disabled", + rm_name); + nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, no ? "true" : "false"); + return nb_cli_apply_changes(vty, NULL); +} + static int route_map_config_write(struct vty *vty) { struct lyd_node *dnode; @@ -1447,6 +1515,7 @@ void route_map_cli_init(void) install_element(CONFIG_NODE, &route_map_cmd); install_element(CONFIG_NODE, &no_route_map_cmd); install_element(CONFIG_NODE, &no_route_map_all_cmd); + install_element(CONFIG_NODE, &route_map_optimization_cmd); /* Install the on-match stuff */ install_element(RMAP_NODE, &rmap_onmatch_next_cmd); @@ -1513,4 +1582,6 @@ void route_map_cli_init(void) install_element(RMAP_NODE, &set_srte_color_cmd); install_element(RMAP_NODE, &no_set_srte_color_cmd); + + install_element(RMAP_NODE, &routemap_optimization_cmd); } diff --git a/lib/routemap_northbound.c b/lib/routemap_northbound.c index 410eb51f5e..db06e9caac 100644 --- a/lib/routemap_northbound.c +++ b/lib/routemap_northbound.c @@ -141,6 +141,30 @@ static int lib_route_map_destroy(struct nb_cb_destroy_args *args) } /* + * XPath: /frr-route-map:lib/route-map/optimization-disabled + */ +static int +lib_route_map_optimization_disabled_modify(struct nb_cb_modify_args *args) +{ + struct route_map *rm; + bool disabled = yang_dnode_get_bool(args->dnode, NULL); + + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + /* NOTHING */ + break; + case NB_EV_APPLY: + rm = nb_running_get_entry(args->dnode, NULL, true); + rm->optimization_disabled = disabled; + break; + } + + return NB_OK; +} + +/* * XPath: /frr-route-map:lib/route-map/entry */ static int lib_route_map_entry_create(struct nb_cb_create_args *args) @@ -1198,6 +1222,13 @@ const struct frr_yang_module_info frr_route_map_info = { } }, { + .xpath = "/frr-route-map:lib/route-map/optimization-disabled", + .cbs = { + .modify = lib_route_map_optimization_disabled_modify, + .cli_show = route_map_optimization_disabled_show, + } + }, + { .xpath = "/frr-route-map:lib/route-map/entry", .cbs = { .create = lib_route_map_entry_create, diff --git a/lib/zclient.c b/lib/zclient.c index c78937c1ec..d613906d82 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -3916,6 +3916,21 @@ static int zclient_read(struct thread *thread) (*zclient->zebra_client_close_notify)(command, zclient, length, vrf_id); break; + case ZEBRA_NHRP_NEIGH_ADDED: + if (zclient->neighbor_added) + (*zclient->neighbor_added)(command, zclient, length, + vrf_id); + break; + case ZEBRA_NHRP_NEIGH_REMOVED: + if (zclient->neighbor_removed) + (*zclient->neighbor_removed)(command, zclient, length, + vrf_id); + break; + case ZEBRA_NHRP_NEIGH_GET: + if (zclient->neighbor_get) + (*zclient->neighbor_get)(command, zclient, length, + vrf_id); + break; default: break; } @@ -4181,3 +4196,59 @@ char *zclient_evpn_dump_macip_flags(uint8_t flags, char *buf, size_t len) return buf; } + +static int zclient_neigh_ip_read_entry(struct stream *s, struct ipaddr *add) +{ + uint8_t family; + + STREAM_GETC(s, family); + if (family != AF_INET && family != AF_INET6) + return -1; + + STREAM_GET(&add->ip.addr, s, family2addrsize(family)); + add->ipa_type = family; + return 0; + stream_failure: + return -1; +} + +int zclient_neigh_ip_encode(struct stream *s, + uint16_t cmd, + union sockunion *in, + union sockunion *out, + struct interface *ifp) +{ + int ret = 0; + + zclient_create_header(s, cmd, ifp->vrf_id); + stream_putc(s, sockunion_family(in)); + stream_write(s, sockunion_get_addr(in), sockunion_get_addrlen(in)); + if (out && sockunion_family(out) != AF_UNSPEC) { + stream_putc(s, sockunion_family(out)); + stream_write(s, sockunion_get_addr(out), + sockunion_get_addrlen(out)); + } else + stream_putc(s, AF_UNSPEC); + stream_putl(s, ifp->ifindex); + if (out) + stream_putl(s, ZEBRA_NEIGH_STATE_REACHABLE); + else + stream_putl(s, ZEBRA_NEIGH_STATE_FAILED); + return ret; +} + +int zclient_neigh_ip_decode(struct stream *s, struct zapi_neigh_ip *api) +{ + int ret; + + ret = zclient_neigh_ip_read_entry(s, &api->ip_in); + if (ret < 0) + return -1; + zclient_neigh_ip_read_entry(s, &api->ip_out); + + STREAM_GETL(s, api->index); + STREAM_GETL(s, api->ndm_state); + return 0; + stream_failure: + return -1; +} diff --git a/lib/zclient.h b/lib/zclient.h index bd952ea1e6..90240e40b2 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -23,6 +23,7 @@ /* For struct zapi_route. */ #include "prefix.h" +#include "ipaddr.h" /* For struct interface and struct connected. */ #include "if.h" @@ -223,6 +224,14 @@ typedef enum { ZEBRA_NEIGH_DISCOVER, ZEBRA_ROUTE_NOTIFY_REQUEST, ZEBRA_CLIENT_CLOSE_NOTIFY, + ZEBRA_NHRP_NEIGH_ADDED, + ZEBRA_NHRP_NEIGH_REMOVED, + ZEBRA_NHRP_NEIGH_GET, + ZEBRA_NHRP_NEIGH_REGISTER, + ZEBRA_NHRP_NEIGH_UNREGISTER, + ZEBRA_NEIGH_IP_ADD, + ZEBRA_NEIGH_IP_DEL, + ZEBRA_CONFIGURE_ARP, } zebra_message_types_t; enum zebra_error_types { @@ -381,6 +390,9 @@ struct zclient { int (*opaque_unregister_handler)(ZAPI_CALLBACK_ARGS); int (*sr_policy_notify_status)(ZAPI_CALLBACK_ARGS); int (*zebra_client_close_notify)(ZAPI_CALLBACK_ARGS); + void (*neighbor_added)(ZAPI_CALLBACK_ARGS); + void (*neighbor_removed)(ZAPI_CALLBACK_ARGS); + void (*neighbor_get)(ZAPI_CALLBACK_ARGS); }; /* Zebra API message flag. */ @@ -794,6 +806,27 @@ struct zclient_options { extern struct zclient_options zclient_options_default; +/* link layer representation for GRE like interfaces + * ip_in is the underlay IP, ip_out is the tunnel dest + * index stands for the index of the interface + * ndm state stands for the NDM value in netlink + */ +#define ZEBRA_NEIGH_STATE_REACHABLE (0x02) +#define ZEBRA_NEIGH_STATE_FAILED (0x20) +struct zapi_neigh_ip { + int cmd; + struct ipaddr ip_in; + struct ipaddr ip_out; + ifindex_t index; + uint32_t ndm_state; +}; +int zclient_neigh_ip_decode(struct stream *s, struct zapi_neigh_ip *api); +int zclient_neigh_ip_encode(struct stream *s, + uint16_t cmd, + union sockunion *in, + union sockunion *out, + struct interface *ifp); + /* * We reserve the top 4 bits for l2-NHG, everything else * is for zebra/proto l3-NHG. |
