📄 ospf_zebra.c
字号:
/* * Zebra connect library for OSPFd * Copyright (C) 1997, 98, 99, 2000 Kunihiro Ishiguro, Toshiaki Takada * * This file is part of GNU Zebra. * * GNU Zebra is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2, or (at your option) any * later version. * * GNU Zebra is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNU Zebra; see the file COPYING. If not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */#include <zebra.h>#include "thread.h"#include "command.h"#include "network.h"#include "prefix.h"#include "routemap.h"#include "table.h"#include "stream.h"#include "memory.h"#include "zclient.h"#include "filter.h"#include "log.h"#include "ospfd/ospfd.h"#include "ospfd/ospf_interface.h"#include "ospfd/ospf_ism.h"#include "ospfd/ospf_asbr.h"#include "ospfd/ospf_asbr.h"#include "ospfd/ospf_abr.h"#include "ospfd/ospf_lsa.h"#include "ospfd/ospf_dump.h"#include "ospfd/ospf_route.h"#include "ospfd/ospf_zebra.h"#ifdef HAVE_SNMP#include "ospfd/ospf_snmp.h"#endif /* HAVE_SNMP *//* Zebra structure to hold current status. */struct zclient *zclient = NULL;/* For registering threads. */extern struct thread_master *master;/* Inteface addition message from zebra. */intospf_interface_add (int command, struct zclient *zclient, zebra_size_t length){ struct interface *ifp; struct ospf *ospf; ifp = zebra_interface_add_read (zclient->ibuf); if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE)) zlog_info ("Zebra: interface add %s index %d flags %ld metric %d mtu %d", ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu); if (!OSPF_IF_PARAM_CONFIGURED (IF_DEF_PARAMS (ifp), type)) { SET_IF_PARAM (IF_DEF_PARAMS (ifp), type); IF_DEF_PARAMS (ifp)->type = OSPF_IFTYPE_BROADCAST; if (if_is_broadcast (ifp)) IF_DEF_PARAMS (ifp)->type = OSPF_IFTYPE_BROADCAST; else if (if_is_pointopoint (ifp)) IF_DEF_PARAMS (ifp)->type = OSPF_IFTYPE_POINTOPOINT; else if (if_is_loopback (ifp)) IF_DEF_PARAMS (ifp)->type = OSPF_IFTYPE_LOOPBACK; } ospf = ospf_lookup (); if (ospf != NULL) ospf_if_update (ospf);#ifdef HAVE_SNMP ospf_snmp_if_update (ifp);#endif /* HAVE_SNMP */ return 0;}intospf_interface_delete (int command, struct zclient *zclient, zebra_size_t length){ struct interface *ifp; struct stream *s; struct route_node *rn; s = zclient->ibuf; /* zebra_interface_state_read() updates interface structure in iflist */ ifp = zebra_interface_state_read (s); if (ifp == NULL) return 0; if (if_is_up (ifp)) zlog_warn ("Zebra: got delete of %s, but interface is still up", ifp->name); if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE)) zlog_info ("Zebra: interface delete %s index %d flags %ld metric %d mtu %d", ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu); #ifdef HAVE_SNMP ospf_snmp_if_delete (ifp);#endif /* HAVE_SNMP */ for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn)) if (rn->info) ospf_if_free ((struct ospf_interface *) rn->info); for (rn = route_top (IF_OIFS_PARAMS (ifp)); rn; rn = route_next (rn)) if (rn->info) ospf_del_if_params (rn->info); if_delete (ifp); return 0;}struct interface *zebra_interface_if_lookup (struct stream *s){ struct interface *ifp; u_char ifname_tmp[INTERFACE_NAMSIZ]; /* Read interface name. */ stream_get (ifname_tmp, s, INTERFACE_NAMSIZ); /* Lookup this by interface index. */ ifp = if_lookup_by_name (ifname_tmp); /* If such interface does not exist, indicate an error */ if (!ifp) return NULL; return ifp;}voidzebra_interface_if_set_value (struct stream *s, struct interface *ifp){ /* Read interface's index. */ ifp->ifindex = stream_getl (s); /* Read interface's value. */ ifp->flags = stream_getl (s); ifp->metric = stream_getl (s); ifp->mtu = stream_getl (s); ifp->bandwidth = stream_getl (s);}intospf_interface_state_up (int command, struct zclient *zclient, zebra_size_t length){ struct interface *ifp; struct interface if_tmp; struct ospf_interface *oi; struct route_node *rn; ifp = zebra_interface_if_lookup (zclient->ibuf); if (ifp == NULL) return 0; /* Interface is already up. */ if (if_is_up (ifp)) { /* Temporarily keep ifp values. */ memcpy (&if_tmp, ifp, sizeof (struct interface)); zebra_interface_if_set_value (zclient->ibuf, ifp); if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE)) zlog_info ("Zebra: Interface[%s] state update.", ifp->name); if (if_tmp.bandwidth != ifp->bandwidth) { if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE)) zlog_info ("Zebra: Interface[%s] bandwidth change %d -> %d.", ifp->name, if_tmp.bandwidth, ifp->bandwidth); ospf_if_recalculate_output_cost (ifp); } return 0; } zebra_interface_if_set_value (zclient->ibuf, ifp); if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE)) zlog_info ("Zebra: Interface[%s] state change to up.", ifp->name); for (rn = route_top (IF_OIFS (ifp));rn; rn = route_next (rn)) { if ( (oi = rn->info) == NULL) continue; ospf_if_up (oi); } return 0;}intospf_interface_state_down (int command, struct zclient *zclient, zebra_size_t length){ struct interface *ifp; struct ospf_interface *oi; struct route_node *node; ifp = zebra_interface_state_read (zclient->ibuf); if (ifp == NULL) return 0; if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE)) zlog_info ("Zebra: Interface[%s] state change to down.", ifp->name); for (node = route_top (IF_OIFS (ifp));node; node = route_next (node)) { if ( (oi = node->info) == NULL) continue; ospf_if_down (oi); } return 0;}intospf_interface_address_add (int command, struct zclient *zclient, zebra_size_t length){ struct ospf *ospf; struct connected *c; c = zebra_interface_address_add_read (zclient->ibuf); if (c == NULL) return 0; ospf = ospf_lookup (); if (ospf != NULL) ospf_if_update (ospf);#ifdef HAVE_SNMP ospf_snmp_if_update (c->ifp);#endif /* HAVE_SNMP */ return 0;}intospf_interface_address_delete (int command, struct zclient *zclient, zebra_size_t length){ struct ospf *ospf; struct connected *c; struct interface *ifp; struct ospf_interface *oi; struct route_node *rn; struct prefix p; c = zebra_interface_address_delete_read (zclient->ibuf); if (c == NULL) return 0; ifp = c->ifp; p = *c->address; p.prefixlen = IPV4_MAX_PREFIXLEN; rn = route_node_lookup (IF_OIFS (ifp), &p); if (! rn) return 0; assert (rn->info); oi = rn->info; /* Call interface hook functions to clean up */ ospf_if_free (oi); #ifdef HAVE_SNMP ospf_snmp_if_update (c->ifp);#endif /* HAVE_SNMP */ connected_free (c); ospf = ospf_lookup (); if (ospf != NULL) ospf_if_update (ospf); return 0;}voidospf_zebra_add (struct prefix_ipv4 *p, struct ospf_route *or){ u_char message; u_char distance; u_char flags; int psize; struct stream *s; struct ospf_path *path; listnode node; if (zclient->redist[ZEBRA_ROUTE_OSPF]) { message = 0; flags = 0; /* OSPF pass nexthop and metric */ SET_FLAG (message, ZAPI_MESSAGE_NEXTHOP); SET_FLAG (message, ZAPI_MESSAGE_METRIC); /* Distance value. */ distance = ospf_distance_apply (p, or); if (distance) SET_FLAG (message, ZAPI_MESSAGE_DISTANCE); /* Make packet. */ s = zclient->obuf; stream_reset (s); /* Length place holder. */ stream_putw (s, 0); /* Put command, type, flags, message. */ stream_putc (s, ZEBRA_IPV4_ROUTE_ADD); stream_putc (s, ZEBRA_ROUTE_OSPF); stream_putc (s, flags); stream_putc (s, message); /* Put prefix information. */ psize = PSIZE (p->prefixlen); stream_putc (s, p->prefixlen); stream_write (s, (u_char *)&p->prefix, psize); /* Nexthop count. */ stream_putc (s, or->path->count); /* Nexthop, ifindex, distance and metric information. */ for (node = listhead (or->path); node; nextnode (node)) { path = getdata (node); if (path->nexthop.s_addr != INADDR_ANY) { stream_putc (s, ZEBRA_NEXTHOP_IPV4); stream_put_in_addr (s, &path->nexthop); } else { stream_putc (s, ZEBRA_NEXTHOP_IFINDEX); if (path->oi) stream_putl (s, path->oi->ifp->ifindex); else stream_putl (s, 0); } } if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE)) stream_putc (s, distance); if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC)) { if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL) stream_putl (s, or->cost + or->u.ext.type2_cost); else if (or->path_type == OSPF_PATH_TYPE2_EXTERNAL) stream_putl (s, or->u.ext.type2_cost); else stream_putl (s, or->cost); } stream_putw_at (s, 0, stream_get_endp (s)); writen (zclient->sock, s->data, stream_get_endp (s));#if 0 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE)) { char *nexthop_str; nexthop_str = strdup (inet_ntoa (*nexthop)); zlog_info ("Zebra: Route add %s/%d nexthop %s metric %d", inet_ntoa (p->prefix), p->prefixlen, nexthop_str, metric); free (nexthop_str); }#endif /* 0 */ }}voidospf_zebra_delete (struct prefix_ipv4 *p, struct ospf_route *or){ struct zapi_ipv4 api; if (zclient->redist[ZEBRA_ROUTE_OSPF]) { api.type = ZEBRA_ROUTE_OSPF; api.flags = 0; api.message = 0; zapi_ipv4_delete (zclient, p, &api);#if 0 if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE)) { char *nexthop_str; nexthop_str = strdup (inet_ntoa (*nexthop)); zlog_info ("Zebra: Route delete %s/%d nexthop %s", inet_ntoa (p->prefix), p->prefixlen, nexthop_str); free (nexthop_str); }#endif /* 0 */ }}voidospf_zebra_add_discard (struct prefix_ipv4 *p){ struct zapi_ipv4 api; if (zclient->redist[ZEBRA_ROUTE_OSPF]) { api.type = ZEBRA_ROUTE_OSPF; api.flags = ZEBRA_FLAG_BLACKHOLE; api.message = 0; SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); api.nexthop_num = 0; api.ifindex_num = 0; zapi_ipv4_add (zclient, p, &api); }}voidospf_zebra_delete_discard (struct prefix_ipv4 *p){ struct zapi_ipv4 api; if (zclient->redist[ZEBRA_ROUTE_OSPF]) { api.type = ZEBRA_ROUTE_OSPF; api.flags = ZEBRA_FLAG_BLACKHOLE; api.message = 0; SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); api.nexthop_num = 0; api.ifindex_num = 0; zapi_ipv4_delete (zclient, p, &api); }}intospf_is_type_redistributed (int type){ return (DEFAULT_ROUTE_TYPE (type)) ? zclient->default_information : zclient->redist[type];}intospf_redistribute_set (struct ospf *ospf, int type, int mtype, int mvalue){ int force = 0; if (ospf_is_type_redistributed (type)) { if (mtype != ospf->dmetric[type].type) { ospf->dmetric[type].type = mtype; force = LSA_REFRESH_FORCE; } if (mvalue != ospf->dmetric[type].value) { ospf->dmetric[type].value = mvalue; force = LSA_REFRESH_FORCE; } ospf_external_lsa_refresh_type (ospf, type, force); if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE)) zlog_info ("Redistribute[%s]: Refresh Type[%d], Metric[%d]", LOOKUP (ospf_redistributed_proto, type), metric_type (ospf, type), metric_value (ospf, type)); return CMD_SUCCESS; } ospf->dmetric[type].type = mtype; ospf->dmetric[type].value = mvalue; zclient_redistribute_set (zclient, type); if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE)) zlog_info ("Redistribute[%s]: Start Type[%d], Metric[%d]", LOOKUP (ospf_redistributed_proto, type), metric_type (ospf, type), metric_value (ospf, type)); ospf_asbr_status_update (ospf, ++ospf->redistribute); return CMD_SUCCESS;}intospf_redistribute_unset (struct ospf *ospf, int type){ if (type == zclient->redist_default) return CMD_SUCCESS; if (! ospf_is_type_redistributed (type)) return CMD_SUCCESS; zclient_redistribute_unset (zclient, type); if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE)) zlog_info ("Redistribute[%s]: Stop", LOOKUP (ospf_redistributed_proto, type)); ospf->dmetric[type].type = -1; ospf->dmetric[type].value = -1; /* Remove the routes from OSPF table. */ ospf_redistribute_withdraw (type); ospf_asbr_status_update (ospf, --ospf->redistribute); return CMD_SUCCESS;}intospf_redistribute_default_set (struct ospf *ospf, int originate, int mtype, int mvalue){ int force = 0; if (ospf_is_type_redistributed (DEFAULT_ROUTE)) { if (mtype != ospf->dmetric[DEFAULT_ROUTE].type) { ospf->dmetric[DEFAULT_ROUTE].type = mtype; force = 1; } if (mvalue != ospf->dmetric[DEFAULT_ROUTE].value) { force = 1; ospf->dmetric[DEFAULT_ROUTE].value = mvalue; } ospf_external_lsa_refresh_default (ospf); if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE)) zlog_info ("Redistribute[%s]: Refresh Type[%d], Metric[%d]", LOOKUP (ospf_redistributed_proto, DEFAULT_ROUTE), metric_type (ospf, DEFAULT_ROUTE), metric_value (ospf, DEFAULT_ROUTE)); return CMD_SUCCESS; } ospf->default_originate = originate; ospf->dmetric[DEFAULT_ROUTE].type = mtype; ospf->dmetric[DEFAULT_ROUTE].value = mvalue; zclient_redistribute_default_set (zclient); if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE)) zlog_info ("Redistribute[DEFAULT]: Start Type[%d], Metric[%d]", metric_type (ospf, DEFAULT_ROUTE),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -