1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* route-map for interface.
3 * Copyright (C) 1999 Kunihiro Ishiguro
13 #include "ripd/ripd.h"
15 DEFINE_MTYPE_STATIC(LIB
, IF_RMAP_CTX
, "Interface route map container");
16 DEFINE_MTYPE_STATIC(LIB
, IF_RMAP_CTX_NAME
,
17 "Interface route map container name");
18 DEFINE_MTYPE_STATIC(LIB
, IF_RMAP
, "Interface route map");
19 DEFINE_MTYPE_STATIC(LIB
, IF_RMAP_NAME
, "I.f. route map name");
21 static struct list
*if_rmap_ctx_list
;
23 static struct if_rmap
*if_rmap_new(void)
27 new = XCALLOC(MTYPE_IF_RMAP
, sizeof(struct if_rmap
));
32 static void if_rmap_free(struct if_rmap
*if_rmap
)
34 XFREE(MTYPE_IF_RMAP_NAME
, if_rmap
->ifname
);
36 XFREE(MTYPE_IF_RMAP_NAME
, if_rmap
->routemap
[IF_RMAP_IN
]);
37 XFREE(MTYPE_IF_RMAP_NAME
, if_rmap
->routemap
[IF_RMAP_OUT
]);
39 XFREE(MTYPE_IF_RMAP
, if_rmap
);
42 struct if_rmap
*if_rmap_lookup(struct if_rmap_ctx
*ctx
, const char *ifname
)
45 struct if_rmap
*if_rmap
;
48 key
.ifname
= (ifname
) ? XSTRDUP(MTYPE_IF_RMAP_NAME
, ifname
) : NULL
;
50 if_rmap
= hash_lookup(ctx
->ifrmaphash
, &key
);
52 XFREE(MTYPE_IF_RMAP_NAME
, key
.ifname
);
57 void if_rmap_hook_add(struct if_rmap_ctx
*ctx
,
58 void (*func
)(struct if_rmap_ctx
*ctx
,
61 ctx
->if_rmap_add_hook
= func
;
64 void if_rmap_hook_delete(struct if_rmap_ctx
*ctx
,
65 void (*func
)(struct if_rmap_ctx
*ctx
,
68 ctx
->if_rmap_delete_hook
= func
;
71 static void *if_rmap_hash_alloc(void *arg
)
73 struct if_rmap
*ifarg
= (struct if_rmap
*)arg
;
74 struct if_rmap
*if_rmap
;
76 if_rmap
= if_rmap_new();
77 if_rmap
->ifname
= XSTRDUP(MTYPE_IF_RMAP_NAME
, ifarg
->ifname
);
82 static struct if_rmap
*if_rmap_get(struct if_rmap_ctx
*ctx
, const char *ifname
)
88 key
.ifname
= (ifname
) ? XSTRDUP(MTYPE_IF_RMAP_NAME
, ifname
) : NULL
;
90 ret
= hash_get(ctx
->ifrmaphash
, &key
, if_rmap_hash_alloc
);
92 XFREE(MTYPE_IF_RMAP_NAME
, key
.ifname
);
97 static unsigned int if_rmap_hash_make(const void *data
)
99 const struct if_rmap
*if_rmap
= data
;
101 return string_hash_make(if_rmap
->ifname
);
104 static bool if_rmap_hash_cmp(const void *arg1
, const void *arg2
)
106 const struct if_rmap
*if_rmap1
= arg1
;
107 const struct if_rmap
*if_rmap2
= arg2
;
109 return strcmp(if_rmap1
->ifname
, if_rmap2
->ifname
) == 0;
112 static struct if_rmap
*if_rmap_set(struct if_rmap_ctx
*ctx
,
113 const char *ifname
, enum if_rmap_type type
,
114 const char *routemap_name
)
116 struct if_rmap
*if_rmap
;
118 if_rmap
= if_rmap_get(ctx
, ifname
);
120 if (type
== IF_RMAP_IN
) {
121 XFREE(MTYPE_IF_RMAP_NAME
, if_rmap
->routemap
[IF_RMAP_IN
]);
122 if_rmap
->routemap
[IF_RMAP_IN
] =
123 XSTRDUP(MTYPE_IF_RMAP_NAME
, routemap_name
);
125 if (type
== IF_RMAP_OUT
) {
126 XFREE(MTYPE_IF_RMAP_NAME
, if_rmap
->routemap
[IF_RMAP_OUT
]);
127 if_rmap
->routemap
[IF_RMAP_OUT
] =
128 XSTRDUP(MTYPE_IF_RMAP_NAME
, routemap_name
);
131 if (ctx
->if_rmap_add_hook
)
132 (ctx
->if_rmap_add_hook
)(ctx
, if_rmap
);
137 static int if_rmap_unset(struct if_rmap_ctx
*ctx
,
138 const char *ifname
, enum if_rmap_type type
,
139 const char *routemap_name
)
141 struct if_rmap
*if_rmap
;
143 if_rmap
= if_rmap_lookup(ctx
, ifname
);
147 if (type
== IF_RMAP_IN
) {
148 if (!if_rmap
->routemap
[IF_RMAP_IN
])
150 if (strcmp(if_rmap
->routemap
[IF_RMAP_IN
], routemap_name
) != 0)
153 XFREE(MTYPE_IF_RMAP_NAME
, if_rmap
->routemap
[IF_RMAP_IN
]);
156 if (type
== IF_RMAP_OUT
) {
157 if (!if_rmap
->routemap
[IF_RMAP_OUT
])
159 if (strcmp(if_rmap
->routemap
[IF_RMAP_OUT
], routemap_name
) != 0)
162 XFREE(MTYPE_IF_RMAP_NAME
, if_rmap
->routemap
[IF_RMAP_OUT
]);
165 if (ctx
->if_rmap_delete_hook
)
166 ctx
->if_rmap_delete_hook(ctx
, if_rmap
);
168 if (if_rmap
->routemap
[IF_RMAP_IN
] == NULL
169 && if_rmap
->routemap
[IF_RMAP_OUT
] == NULL
) {
170 hash_release(ctx
->ifrmaphash
, if_rmap
);
171 if_rmap_free(if_rmap
);
179 "route-map RMAP_NAME <in|out> IFNAME",
182 "Route map set for input filtering\n"
183 "Route map set for output filtering\n"
184 "Route map interface name\n")
186 int idx_rmap_name
= 1;
189 enum if_rmap_type type
;
190 struct if_rmap_ctx
*ctx
;
191 const struct lyd_node
*dnode
;
194 dnode
= yang_dnode_get(running_config
->dnode
, VTY_CURR_XPATH
);
195 rip
= nb_running_get_entry(dnode
, NULL
, true);
196 ctx
= rip
->if_rmap_ctx
;
198 if (strncmp(argv
[idx_in_out
]->text
, "in", 1) == 0)
200 else if (strncmp(argv
[idx_in_out
]->text
, "out", 1) == 0)
203 vty_out(vty
, "route-map direction must be [in|out]\n");
204 return CMD_WARNING_CONFIG_FAILED
;
207 if_rmap_set(ctx
, argv
[idx_ifname
]->arg
,
208 type
, argv
[idx_rmap_name
]->arg
);
215 "no route-map ROUTEMAP_NAME <in|out> IFNAME",
219 "Route map for input filtering\n"
220 "Route map for output filtering\n"
221 "Route map interface name\n")
223 int idx_routemap_name
= 2;
227 enum if_rmap_type type
;
228 struct if_rmap_ctx
*ctx
=
229 (struct if_rmap_ctx
*)listnode_head(if_rmap_ctx_list
);
231 if (strncmp(argv
[idx_in_out
]->arg
, "i", 1) == 0)
233 else if (strncmp(argv
[idx_in_out
]->arg
, "o", 1) == 0)
236 vty_out(vty
, "route-map direction must be [in|out]\n");
237 return CMD_WARNING_CONFIG_FAILED
;
240 ret
= if_rmap_unset(ctx
, argv
[idx_ifname
]->arg
, type
,
241 argv
[idx_routemap_name
]->arg
);
243 vty_out(vty
, "route-map doesn't exist\n");
244 return CMD_WARNING_CONFIG_FAILED
;
250 /* Configuration write function. */
251 int config_write_if_rmap(struct vty
*vty
,
252 struct if_rmap_ctx
*ctx
)
255 struct hash_bucket
*mp
;
257 struct hash
*ifrmaphash
= ctx
->ifrmaphash
;
259 for (i
= 0; i
< ifrmaphash
->size
; i
++)
260 for (mp
= ifrmaphash
->index
[i
]; mp
; mp
= mp
->next
) {
261 struct if_rmap
*if_rmap
;
265 if (if_rmap
->routemap
[IF_RMAP_IN
]) {
266 vty_out(vty
, " route-map %s in %s\n",
267 if_rmap
->routemap
[IF_RMAP_IN
],
272 if (if_rmap
->routemap
[IF_RMAP_OUT
]) {
273 vty_out(vty
, " route-map %s out %s\n",
274 if_rmap
->routemap
[IF_RMAP_OUT
],
282 void if_rmap_ctx_delete(struct if_rmap_ctx
*ctx
)
284 listnode_delete(if_rmap_ctx_list
, ctx
);
285 hash_clean_and_free(&ctx
->ifrmaphash
, (void (*)(void *))if_rmap_free
);
287 XFREE(MTYPE_IF_RMAP_CTX_NAME
, ctx
->name
);
288 XFREE(MTYPE_IF_RMAP_CTX
, ctx
);
291 /* name is optional: either vrf name, or other */
292 struct if_rmap_ctx
*if_rmap_ctx_create(const char *name
)
294 struct if_rmap_ctx
*ctx
;
296 ctx
= XCALLOC(MTYPE_IF_RMAP_CTX
, sizeof(struct if_rmap_ctx
));
298 ctx
->name
= XSTRDUP(MTYPE_IF_RMAP_CTX_NAME
, name
);
299 ctx
->ifrmaphash
= hash_create_size(4, if_rmap_hash_make
, if_rmap_hash_cmp
,
300 "Interface Route-Map Hash");
301 if (!if_rmap_ctx_list
)
302 if_rmap_ctx_list
= list_new();
303 listnode_add(if_rmap_ctx_list
, ctx
);
307 void if_rmap_init(int node
)
309 if (node
== RIPNG_NODE
) {
310 } else if (node
== RIP_NODE
) {
311 install_element(RIP_NODE
, &if_rmap_cmd
);
312 install_element(RIP_NODE
, &no_if_rmap_cmd
);
314 if_rmap_ctx_list
= list_new();
317 void if_rmap_terminate(void)
319 if (!if_rmap_ctx_list
)
321 list_delete(&if_rmap_ctx_list
);