mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-05-29 15:07:51 +00:00

——————————————------------- - etc/init.d/quagga is modified to support creating separate ospf daemon process for each instance. Each individual instance is monitored by watchquagga just like any protocol daemons.(requires initd-mi.patch). - Vtysh is modified to able to connect to multiple daemons of the same protocol (supported for OSPF only for now). - ospfd is modified to remember the Instance-ID that its invoked with. For the entire life of the process it caters to any command request that matches that instance-ID (unless its a non instance specific command). Routes/messages to zebra are tagged with instance-ID. - zebra route/redistribute mechanisms are modified to work with [protocol type + instance-id] - bgpd now has ability to have multiple instance specific redistribution for a protocol (OSPF only supported/tested for now). - zlog ability to display instance-id besides the protocol/daemon name. - Changes in other daemons are to because of the needed integration with some of the modified APIs/routines. (Didn’t prefer replicating too many separate instance specific APIs.) - config/show/debug commands are modified to take instance-id argument as appropriate. Guidelines to start using multi-instance ospf --------------------------------------------- The patch is backward compatible, i.e for any previous way of single ospf deamon(router ospf <cr>) will continue to work as is, including all the show commands etc. To enable multiple instances, do the following: 1. service quagga stop 2. Modify /etc/quagga/daemons to add instance-ids of each desired instance in the following format: ospfd=“yes" ospfd_instances="1,2,3" assuming you want to enable 3 instances with those instance ids. 3. Create corresponding ospfd config files as ospfd-1.conf, ospfd-2.conf and ospfd-3.conf. 4. service quagga start/restart 5. Verify that the deamons are started as expected. You should see ospfd started with -n <instance-id> option. ps –ef | grep quagga With that /var/run/quagga/ should have ospfd-<instance-id>.pid and ospfd-<instance-id>/vty to each instance. 6. vtysh to work with instances as you would with any other deamons. 7. Overall most quagga semantics are the same working with the instance deamon, like it is for any other daemon. NOTE: To safeguard against errors leading to too many processes getting invoked, a hard limit on number of instance-ids is in place, currently its 5. Allowed instance-id range is <1-65535> Once daemons are up, show running from vtysh should show the instance-id of each daemon as 'router ospf <instance-id>’ (without needing explicit configuration) Instance-id can not be changed via vtysh, other router ospf configuration is allowed as before. Signed-off-by: Vipin Kumar <vipin@cumulusnetworks.com> Reviewed-by: Daniel Walton <dwalton@cumulusnetworks.com> Reviewed-by: Dinesh G Dutt <ddutt@cumulusnetworks.com>
371 lines
7.9 KiB
C
371 lines
7.9 KiB
C
/*
|
|
* IS-IS Rout(e)ing protocol - isis_main.c
|
|
*
|
|
* Copyright (C) 2001,2002 Sampo Saaristo
|
|
* Tampere University of Technology
|
|
* Institute of Communications Engineering
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public Licenseas published by the Free
|
|
* Software Foundation; either version 2 of the License, or (at your option)
|
|
* any later version.
|
|
*
|
|
* This program 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 this program; if not, write to the Free Software Foundation, Inc.,
|
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#include <zebra.h>
|
|
|
|
#include "getopt.h"
|
|
#include "thread.h"
|
|
#include "log.h"
|
|
#include <lib/version.h>
|
|
#include "command.h"
|
|
#include "vty.h"
|
|
#include "memory.h"
|
|
#include "stream.h"
|
|
#include "if.h"
|
|
#include "privs.h"
|
|
#include "sigevent.h"
|
|
#include "filter.h"
|
|
#include "zclient.h"
|
|
|
|
#include "isisd/dict.h"
|
|
#include "include-netbsd/iso.h"
|
|
#include "isisd/isis_constants.h"
|
|
#include "isisd/isis_common.h"
|
|
#include "isisd/isis_flags.h"
|
|
#include "isisd/isis_circuit.h"
|
|
#include "isisd/isisd.h"
|
|
#include "isisd/isis_dynhn.h"
|
|
#include "isisd/isis_spf.h"
|
|
#include "isisd/isis_route.h"
|
|
#include "isisd/isis_zebra.h"
|
|
|
|
/* Default configuration file name */
|
|
#define ISISD_DEFAULT_CONFIG "isisd.conf"
|
|
/* Default vty port */
|
|
#define ISISD_VTY_PORT 2608
|
|
|
|
/* isisd privileges */
|
|
zebra_capabilities_t _caps_p[] = {
|
|
ZCAP_NET_RAW,
|
|
ZCAP_BIND
|
|
};
|
|
|
|
struct zebra_privs_t isisd_privs = {
|
|
#if defined(QUAGGA_USER)
|
|
.user = QUAGGA_USER,
|
|
#endif
|
|
#if defined QUAGGA_GROUP
|
|
.group = QUAGGA_GROUP,
|
|
#endif
|
|
#ifdef VTY_GROUP
|
|
.vty_group = VTY_GROUP,
|
|
#endif
|
|
.caps_p = _caps_p,
|
|
.cap_num_p = sizeof (_caps_p) / sizeof (*_caps_p),
|
|
.cap_num_i = 0
|
|
};
|
|
|
|
/* isisd options */
|
|
struct option longopts[] = {
|
|
{"daemon", no_argument, NULL, 'd'},
|
|
{"config_file", required_argument, NULL, 'f'},
|
|
{"pid_file", required_argument, NULL, 'i'},
|
|
{"socket", required_argument, NULL, 'z'},
|
|
{"vty_addr", required_argument, NULL, 'A'},
|
|
{"vty_port", required_argument, NULL, 'P'},
|
|
{"user", required_argument, NULL, 'u'},
|
|
{"group", required_argument, NULL, 'g'},
|
|
{"version", no_argument, NULL, 'v'},
|
|
{"dryrun", no_argument, NULL, 'C'},
|
|
{"help", no_argument, NULL, 'h'},
|
|
{0}
|
|
};
|
|
|
|
/* Configuration file and directory. */
|
|
char config_default[] = SYSCONFDIR ISISD_DEFAULT_CONFIG;
|
|
char *config_file = NULL;
|
|
|
|
/* isisd program name. */
|
|
char *progname;
|
|
|
|
int daemon_mode = 0;
|
|
|
|
/* Master of threads. */
|
|
struct thread_master *master;
|
|
|
|
/* Process ID saved for use by init system */
|
|
const char *pid_file = PATH_ISISD_PID;
|
|
|
|
/* for reload */
|
|
char _cwd[MAXPATHLEN];
|
|
char _progpath[MAXPATHLEN];
|
|
int _argc;
|
|
char **_argv;
|
|
char **_envp;
|
|
|
|
/*
|
|
* Prototypes.
|
|
*/
|
|
void reload(void);
|
|
void sighup(void);
|
|
void sigint(void);
|
|
void sigterm(void);
|
|
void sigusr1(void);
|
|
|
|
|
|
/* Help information display. */
|
|
static void
|
|
usage (int status)
|
|
{
|
|
if (status != 0)
|
|
fprintf (stderr, "Try `%s --help' for more information.\n", progname);
|
|
else
|
|
{
|
|
printf ("Usage : %s [OPTION...]\n\n\
|
|
Daemon which manages IS-IS routing\n\n\
|
|
-d, --daemon Runs in daemon mode\n\
|
|
-f, --config_file Set configuration file name\n\
|
|
-i, --pid_file Set process identifier file name\n\
|
|
-z, --socket Set path of zebra socket\n\
|
|
-A, --vty_addr Set vty's bind address\n\
|
|
-P, --vty_port Set vty's port number\n\
|
|
-u, --user User to run as\n\
|
|
-g, --group Group to run as\n\
|
|
-v, --version Print program version\n\
|
|
-C, --dryrun Check configuration for validity and exit\n\
|
|
-h, --help Display this help and exit\n\
|
|
\n\
|
|
Report bugs to %s\n", progname, ZEBRA_BUG_ADDRESS);
|
|
}
|
|
|
|
exit (status);
|
|
}
|
|
|
|
|
|
void
|
|
reload ()
|
|
{
|
|
zlog_debug ("Reload");
|
|
/* FIXME: Clean up func call here */
|
|
vty_reset ();
|
|
(void) isisd_privs.change (ZPRIVS_RAISE);
|
|
execve (_progpath, _argv, _envp);
|
|
zlog_err ("Reload failed: cannot exec %s: %s", _progpath,
|
|
safe_strerror (errno));
|
|
}
|
|
|
|
static void
|
|
terminate (int i)
|
|
{
|
|
exit (i);
|
|
}
|
|
|
|
/*
|
|
* Signal handlers
|
|
*/
|
|
|
|
void
|
|
sighup (void)
|
|
{
|
|
zlog_debug ("SIGHUP received");
|
|
reload ();
|
|
|
|
return;
|
|
}
|
|
|
|
void
|
|
sigint (void)
|
|
{
|
|
zlog_notice ("Terminating on signal SIGINT");
|
|
terminate (0);
|
|
}
|
|
|
|
void
|
|
sigterm (void)
|
|
{
|
|
zlog_notice ("Terminating on signal SIGTERM");
|
|
terminate (0);
|
|
}
|
|
|
|
void
|
|
sigusr1 (void)
|
|
{
|
|
zlog_debug ("SIGUSR1 received");
|
|
zlog_rotate (NULL);
|
|
}
|
|
|
|
struct quagga_signal_t isisd_signals[] =
|
|
{
|
|
{
|
|
.signal = SIGHUP,
|
|
.handler = &sighup,
|
|
},
|
|
{
|
|
.signal = SIGUSR1,
|
|
.handler = &sigusr1,
|
|
},
|
|
{
|
|
.signal = SIGINT,
|
|
.handler = &sigint,
|
|
},
|
|
{
|
|
.signal = SIGTERM,
|
|
.handler = &sigterm,
|
|
},
|
|
};
|
|
|
|
/*
|
|
* Main routine of isisd. Parse arguments and handle IS-IS state machine.
|
|
*/
|
|
int
|
|
main (int argc, char **argv, char **envp)
|
|
{
|
|
char *p;
|
|
int opt, vty_port = ISISD_VTY_PORT;
|
|
struct thread thread;
|
|
char *config_file = NULL;
|
|
char *vty_addr = NULL;
|
|
int dryrun = 0;
|
|
|
|
/* Get the programname without the preceding path. */
|
|
progname = ((p = strrchr (argv[0], '/')) ? ++p : argv[0]);
|
|
|
|
zlog_default = openzlog (progname, ZLOG_ISIS, 0,
|
|
LOG_CONS | LOG_NDELAY | LOG_PID, LOG_DAEMON);
|
|
|
|
/* for reload */
|
|
_argc = argc;
|
|
_argv = argv;
|
|
_envp = envp;
|
|
getcwd (_cwd, sizeof (_cwd));
|
|
if (*argv[0] == '.')
|
|
snprintf (_progpath, sizeof (_progpath), "%s/%s", _cwd, _argv[0]);
|
|
else
|
|
snprintf (_progpath, sizeof (_progpath), "%s", argv[0]);
|
|
|
|
/* Command line argument treatment. */
|
|
while (1)
|
|
{
|
|
opt = getopt_long (argc, argv, "df:i:z:hA:p:P:u:g:vC", longopts, 0);
|
|
|
|
if (opt == EOF)
|
|
break;
|
|
|
|
switch (opt)
|
|
{
|
|
case 0:
|
|
break;
|
|
case 'd':
|
|
daemon_mode = 1;
|
|
break;
|
|
case 'f':
|
|
config_file = optarg;
|
|
break;
|
|
case 'i':
|
|
pid_file = optarg;
|
|
break;
|
|
case 'z':
|
|
zclient_serv_path_set (optarg);
|
|
break;
|
|
case 'A':
|
|
vty_addr = optarg;
|
|
break;
|
|
case 'P':
|
|
/* Deal with atoi() returning 0 on failure, and isisd not
|
|
listening on isisd port... */
|
|
if (strcmp (optarg, "0") == 0)
|
|
{
|
|
vty_port = 0;
|
|
break;
|
|
}
|
|
vty_port = atoi (optarg);
|
|
vty_port = (vty_port ? vty_port : ISISD_VTY_PORT);
|
|
break;
|
|
case 'u':
|
|
isisd_privs.user = optarg;
|
|
break;
|
|
case 'g':
|
|
isisd_privs.group = optarg;
|
|
break;
|
|
case 'v':
|
|
printf ("ISISd version %s\n", ISISD_VERSION);
|
|
printf ("Copyright (c) 2001-2002 Sampo Saaristo,"
|
|
" Ofer Wald and Hannes Gredler\n");
|
|
print_version ("Zebra");
|
|
exit (0);
|
|
break;
|
|
case 'C':
|
|
dryrun = 1;
|
|
break;
|
|
case 'h':
|
|
usage (0);
|
|
break;
|
|
default:
|
|
usage (1);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* thread master */
|
|
master = thread_master_create ();
|
|
|
|
/* random seed from time */
|
|
srand (time (NULL));
|
|
|
|
/*
|
|
* initializations
|
|
*/
|
|
zprivs_init (&isisd_privs);
|
|
signal_init (master, array_size (isisd_signals), isisd_signals);
|
|
cmd_init (1);
|
|
vty_init (master);
|
|
memory_init ();
|
|
access_list_init();
|
|
isis_init ();
|
|
isis_circuit_init ();
|
|
isis_spf_cmds_init ();
|
|
|
|
/* create the global 'isis' instance */
|
|
isis_new (1);
|
|
|
|
isis_zebra_init ();
|
|
|
|
/* parse config file */
|
|
/* this is needed three times! because we have interfaces before the areas */
|
|
vty_read_config (config_file, config_default);
|
|
|
|
/* Start execution only if not in dry-run mode */
|
|
if (dryrun)
|
|
return(0);
|
|
|
|
/* demonize */
|
|
if (daemon_mode)
|
|
daemon (0, 0);
|
|
|
|
/* Process ID file creation. */
|
|
if (pid_file[0] != '\0')
|
|
pid_output (pid_file);
|
|
|
|
/* Make isis vty socket. */
|
|
vty_serv_sock (vty_addr, vty_port, ISIS_VTYSH_PATH);
|
|
|
|
/* Print banner. */
|
|
zlog_notice ("Quagga-ISISd %s starting: vty@%d", QUAGGA_VERSION, vty_port);
|
|
|
|
/* Start finite state machine. */
|
|
while (thread_fetch (master, &thread))
|
|
thread_call (&thread);
|
|
|
|
/* Not reached. */
|
|
exit (0);
|
|
}
|