Rip source code analysis

Source: Internet
Author: User

Int main (INT argc, char ** argv)

{

Char * P;

Int daemon_mode = 0;

Char * progname;

Struct thread;

/* Set umask before anything for security */

Umask (0027 );

/* Get program name .*/

Progname = (P = strrchr (argv [0], '/')? + P: argv [0]);

/* First of all we need logging init .*/

// Set log here

Zlog_default = openzlog (progname, zlog_nolog, zlog_rip,

Log_cons | log_ndelay | log_pid, log_daemon );

/* Command line option parse .*/

While (1)

{

Int OPT;

// Parse parameters

Opt = getopt_long (argc, argv, "DF: ha: P: RV", longopts, 0 );

If (OPT = EOF)

Break;

Switch (OPT)

{

Case 0:

Break;

Case 'D ':

Daemon_mode = 1;

Break;

Case 'F ':

Config_file = optarg;

Break;

Case 'A ':

Vty_addr = optarg;

Break;

Case 'I ':

Pid_file = optarg;

Break;

Case 'p ':

Vty_port = atoi (optarg );

Break;

Case 'r ':

Retain_mode = 1;

Break;

Case 'V ':

Print_version (progname );

Exit (0 );

Break;

Case 'H ':

Usage (progname, 0 );

Break;

Default:

Usage (progname, 1 );

Break;

}

}

/* Prepare Master thread .*/

Master = thread_master_create ();

/* Library initialization .*/

Signal_init ();

Pai_init (1 );

Vty_init ();

Memory_init ();

Keychain_init ();

/* Rip related initialization .*/

Rip_init ();

Rip_if_init ();

Rip_zclient_init ();

Rip_peer_init ();

/* Sort all installed commands .*/

Sort_node ();

/* Get configuration file .*/

Vty_read_config (config_file, config_current, config_default );

/* Change to the daemon program .*/

If (daemon_mode) // enter the background to run and become a daemon_mode.

Daemon (0, 0 );

/* PID file create .*/

Pid_output (pid_file );

/* Create vty's socket */

Vty_serv_sock (vty_addr, vty_port, rip_vtysh_path );

/* Execute each thread .*/

While (thread_fetch (master, & Thread) // The real execution thread is here

Thread_call (& Thread );

/* Not reached .*/

Exit (0 );

}

First look at the thread_call (& Thread); line, enter this function

Void

Thread_call (struct thread * thread)

{

Unsigned long thread_time;

Rusage_t Ru;

Getrusage (& Thread-> Ru );

(* Thread-> func) (thread); // call the hook function of the thread linked list. For details about the hook function, see

Getrusage (& Ru );

Thread_time = thread_consumed_time (& Ru, & Thread-> Ru );

# Ifdef thread_consumed_time_check

If (thread_time> 200000l)

{

/*

* We have a CPU hog on our hands.

* Whinge about it now, so we're re aware this is yet another task

* To fix.

*/

Zlog_err ("CPU hog task % lx ran for % ldms ",

/* Fixme: report the name of the function somehow */

(Unsigned long) thread-> func,

Thread_time/1000l );

}

# Endif/* thread_consumed_time_check */

}

Check thread_fetch and paste the code

Struct thread *

Thread_fetch (struct thread_master * m, struct thread * fetch)

{

Int num;

Int ready;

Struct thread * thread;

Fd_set readfd;

Fd_set writefd;

Fd_set limit TFD;

Struct timeval timer_now;

Struct timeval timer_val;

Struct timeval * timer_wait;

Struct timeval timer_nowait;

Timer_nowait. TV _sec = 0;

Timer_nowait. TV _usec = 0;

While (1)

{

/* Normal event is the highest priority. */The Event event has the highest priority. In fact, it triggers an update. The so-called trigger update means that when the route table changes, it immediately calls the hook function of the thread and broadcasts more messages.

If (thread = thread_trim_head (& M-> event ))! = NULL)

Return thread_run (M, thread, fetch );

/* Execute timer .*/

Gettimeofday (& timer_now, null );

// Check whether timeout occurs here, that is, if a route table item is not updated within 180 s, the corresponding thread is taken from the active linked list and put into the master-> unuse linked list. To put it bluntly, this thread is suspended and no longer executed.

For (thread = m-> timer. Head; thread = thread-> next)

If (timeval_cmp (timer_now, thread-> U. Sands)> = 0)

{

Thread_list_delete (& M-> timer, thread );

Return thread_run (M, thread, fetch );

}

// If a new Rip packet is received, it is read and the select mechanism is used.

/* If there are any ready threads, process top of them .*/

If (thread = thread_trim_head (& M-> ready ))! = NULL)

Return thread_run (M, thread, fetch );

/* Structure copy .*/

Readfd = m-> readfd;

Writefd = m-> writefd;

Required TFD = m-> required TFD;

/* Calculate select wait timer .*/

Timer_wait = thread_timer_wait (M, & timer_val );

Num = select (fd_setsize, & readfd, & writefd, & 1_tfd, timer_wait );

If (num = 0)

Continue;

If (Num <0)

{

If (errno = eintr)

Continue;

Zlog_warn ("select () error: % s", strerror (errno ));

Return NULL;

}

/* Normal priority read thead .*/

Ready = thread_process_fd (M, & M-> Read, & readfd, & M-> readfd );

/* Write thead .*/

Ready = thread_process_fd (M, & M-> write, & writefd, & M-> writefd );

If (thread = thread_trim_head (& M-> ready ))! = NULL)

Return thread_run (M, thread, fetch );

}

}

Through the above analysis, it is found that the RIP is initialized and then enters a while endless loop, in which different thread hook functions are executed according to different priorities. Where are these hook functions registered? Go to the void rip_event (Enum rip_event event, int sock) function of ripd. C.

Void

Rip_event (Enum rip_event event, int sock)

{

Int jitter = 0;

Switch (Event)

{

// Read event. The hook function registered through thread_add_read is rip_read.

Case rip_read:

Rip-> t_read = thread_add_read (master, rip_read, null, sock );

Break;

// Update event. The hook function registered through thread_add_read is rip_update.

Case rip_update_event:

If (rip-> t_update)

{

Thread_cancel (rip-> t_update );

Rip-> t_update = NULL;

}

Jitter = rip_update_jitter (rip-> update_time );

Rip-> t_update =

Thread_add_timer (master, rip_update, null,

Sock? 2: rip-> update_time + jitter );

Break;

// Trigger the update. The hook function registered through thread_add_read is rip_triggered_update.

Case rip_triggered_update:

Printf ("come in rip_triggered_update \ n"); // Jimmy

If (rip-> t_triggered_interval)

Rip-> trigger = 1;

Else if (! Rip-> t_triggered_update)

{

Printf ("add event rip_triggered_update \ n"); // Jimmy

Rip-> t_triggered_update =

Thread_add_event (master, rip_triggered_update, null, 0 );

}

Break;

Default:

Break;

}

}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.