Design of RSVPD for zMPLS
                        ==========================

Schedules (Includes the schedules of LDPD)
==========================================

Phase 1
========
1) Support of Path, Resv, Path Err, Resv Err, Path Tear and Resv Tear Messages.
2) Support of basic RSVP Signaling Objects and TE extensions-RSVP SESSION. SENDER_TEMPLATE, FILTER_SPEC objects (LSP_TUNNEL_IPV4 , LSP_TUNNEL_IPV6) ,and LRO and Label Objects, 
3) Support of only best effort LSps without CSPF and without ERO.
4) Support of best effort LSPs without Resource Reservation.


Phase 2
=========
1) Support of CSPF and interaction with ISIS,OSPF in computing CSPF Paths. May be we need to add TE support 
   in ISIS,OSPF.
2) Support of explicit Objects (ERO/RRO) in setting up explicit routed LSPs without    Reservation.Support of SESSION_ATTRIBUTE, EXPLICIT_ROUTE and RECORD_ROUTE 

Phase 3
=========
1) Development of Resource Manager and support of resource reservation
2) Signaling Reservation objects 

Phase 4
========
1) Integration of Diff serv or desiging new Diffserv code.
2) Support for Diff serv signaling in RSVP-TE 

Phase 5
========
1) Implementation of Diffserv-TE and RSVP Support.
2) RSVP Refresh Reduction Techniques.

Phase 6
========
1) RSVP Graceful Restart Support.


 

FUNCTIONAL SPECIFICATION
=========================

Commands to be supported:

1) mpls router-id loopback <number> (from 0 to 65535) 
   Must be configured.

Action :   
        1) MPLS_NODE is added to lib/command.h with prompt "config-mpls# ".
           Config write is mpls_config_write.
        2) Command "mpls" is added to CONFIG_NODE. This command will change
           the vty->node = MPLS_NODE and vty->index = rm->rsvp.
        3) Command "router-id loopback x" is added to MPLS_NODE.  
        4) MPLS_NODE is added to default_commands in command.c
          (vty->nodeafter exit/quit from MPLS_NODE is CONFIG_NODE.

2) Interface ethx (interface node) 
      mpls traffic-eng tunnels
      mpls traffic-eng refresh-interval <1..1000> (Default 30 seconds)
      mpls traffic-eng refresh-multiple <>        (Default 3)
      mpls traffic-eng hello-interval <0...10000> ms (Default 5 seconds)
      mpls traffic-eng hello-persist  <1-100> (Default 2)
      mpls traffic-eng hello-tolerance <1-100> (Default 3)
      mpls traffic-eng message-bundling (Default Disabled) 
      mpls traffic-eng refresh-reduction (Default Disabled)

Actions: INTERFACE_NODE already exists. So just add the commands and command 
         handlers to INTERFACE_NODE.

3) rsvp set global preemption (rsvp node)
  
ACTION : 1) RSVP_NODE is added in lib/command.h with prompt "config-rsvp# "
            rsvp_config_write () is added in rsvp_vty.c for writing config for
            this node.
         2) "set global preemption" command is added to RSVP_NODE.
         3) The exit/quit commands in lib/command.c is modified to have 
            CONFIG_NODE as parent node for RSVP_NODE.
         4) Default node commands are installed in RSVP_NODE. 
         
4) show mpls rsvp parameters (en node)
   show mpls interfaces

Action: As SHOW_NODE already exists so just add the commands.

Configuring LSPs
 
5)ip explicit-path name xyz
     next-address 30.1.1.1 strict
     next-address 30.1.1.2 loose
     next-address 31.1.1.2 loose
Actions :
         1) A new node RSVP_IP_PATH_NODE is added to lib/command.h. Prompt 
            "config-ip-path #". 
         2) Add command "ip explicit-path name [IFNAME]"
            to it. This command switches to vty->node RSVP_IP_PATH and
            vty->index = path_name.
         3) Install commands "next address ..." to RSVP_IP_PATH_NODE.
         4) Parent node of RSVP_IP_PATH is CONFIG_NODE.
         5) Install defaults in RSVP_IP_PATH.

6)interface Tunnel4
     tunnel mode mpls traffic-eng
     tunnel destination 10.1.1.2
     tunnel mpls traffic-eng cspf
     tunnel mpls traffic-eng path-option 1 (explicit|dynamic) xyz (standby|)

7) access-list test permit tcp 20.1.1.1 0.0.0.255 any
   route-map shortcut permit 10
   match ip address test
   set interface Tunnel 1





Functional Modules
===================
The following blocks provide a very high level architecture of rsvpd.


                                           User Events
                                                |
                                  +----------------------------+
                                  |    VTY Module rsvp_vty.c   |
                       /----------+----------------------------+
                      /                         |
+-------------------+/            +-----------------------------------+
| rsvp_if.c         |             |                                   |        
| struct rsvp_if    |<----------->| rsvpd.c(RSVP Daemon)              | 
+-------------------+<----+       |                                   |
          ^               |       |                                   |         
          |               |       |                                   |
          v               |       | rsvp_master-->threads             | 
+-------------------+     |       |       |                           |
| rsvp_lsp_fsm.c    |     |       |   struct rsvp                     |
| LSP FSMs          |     |       |       |-------rsvp_tunnel_if(Ingr)|
| Changes states of |     |       |       |             /     \       |        
| LSPs on events    |     |       |       |       rsvp_lsp   rsvp_lsp |
+-------------------+     |       |       |                           |
          |               |       |       |-------rsvp_tunnel_if(Egr) |
          |               |       |       |-------rsvp_tunnel)if (Trs)|         
          v               |       +-----------------------------------+
+--------------------+    +--------^----------+                
|  rsvp_lsp.h/c      |             |          |
| struct rsvp_lsp    |   +---------v--------+ |  +------------------+
| LSP State Machine  |   |rsvp_tunnel.h/c   | |  | rsvp_route.c     |          
| struct rsvp_lsp    |   |                  | |  +-------------^----+
|        |      |    |   |struct rsvp_tunnel| |                |
|  rsvp_psb  rsvp_rsb|<->     |        |    | |          +---------------+
| Registers callbacks|   |rsvp_lsp  rsvp_lsp| +--------- | rsvp_zmpls.c  |-->
| with rsvp_softstate|   |                  |            | if_add/del/dn |
| for LSP events     |   |                  |<---------->| route_add/del |
+--------------------+   +------------------+            | addr add/del  |
          ^                                              | lsp add/del   |  
          |rsvp_lsp callbacks                            +---------------+ 
          |                                                          
+--------------------+          +------------------------+
| rsvp_softstate.c   |          | rsvp_packet.c          |       
| struct rsvp_psb    |          | RSVP Packet Processor  |
| struct rsvp_rsb    |<---------|                        |
| struct psb_info    |create/delete/update               |
| struct rsb_info    | psb/rsb  |                        |
| PSB/RSB Event Call |          |                        |
| backs              |          |                        |
+--------------------+          | struct rsvp_msg_hdr    |      
                                | struct rsvp_packet     |
                                | create/decode packets  |
+---------------------+         | reads/writes packets   |  
|                     |decode/encode obj                 |     
| rsvp_obj.c          |<--------| to network             |
| struct rsvp_obj_hdr |         +------------------------+
| All obj/sub defns.  |                     | 
| Insert/Decode Object|                     |
+---------------------+                     |
                                +------------------------+
                                | rsvp_network.c         |              
                                | Handles read/write to  |
                                | socket. Provides       |
                                | abstractions of network|
                                +------------------------+        
                                
                
RSVP Main Module
=================
rsvpd.h

/* The Central Holder of RSVP Stack. This is as per Zebra Framework */

struct rsvp_master
{
   /* RSVP Instance */
   struct list *rsvp;

   /* RSVP Thread Master */
   struct thread_master *master..;

   /* RSVP Start Time */
   time_t start_time;
}

/* Container for statistics data */
struct rsvp_statistics
{
   u_int32_t path_msg_in;
   u_int32_t path_msg_out;

   u_int32_t resv_msg_in;
   u_int32_t resv_msg_out;

   u_int32_t path_err_in;
   u_int32_t path_err_out;

   u_int32_t resv_err_in;
   u_int32_t resv_err_out;

   u_int32_t path_tear_in;
   u_int32_t path_tear_out;

   u_int32_t resv_tear_in;
   u_int32_t resv_tear_out;

   u_int32_t hello_in;
   u_int32_t hello_out;

   u_int32_t resv_conf_in;
   u_int32_t resv_conf_out;
};

/* The Central RSVP Object is as follows:
struct rsvp
{
   /* RSVP Router ID */
   struct in_addr router_id; /* Configured automatically */
   struct in_addr router_id_static; /* Configured Manually */

   /*----------------------------------------------------------------
    * Following params RSVP global Configs. CLI can modify these. 
    *---------------------------------------------------------------*/
   int_32_t cflags;
#HELLO;
#REFRESH_REDUSCTION
#AGGREGATION
   int  v_hello_interval;  /* Interval for Hellos */
   int  v_refresh_interval;/* Interval for refresh*/
   int  v_reopt_interval;  /* Interval for reoptimize an existing LSP*/
   int  v_retry_interval;  /* Interval for retrying a failed lsp */
   u_int32_t  v_retry_max; /* Maxumum retry that can be done in 
                              bringing up the LSP */

   /* Zebra Interface List */
   struct list *iflist;  

   /*------------------------------------------------------------
    * The following four objects are maintained by rsvp_softstate 
    *-----------------------------------------------------------*/
   /* Pointer to the current PSB/RSBs maintained by this daemon */
   void *psbObj; /* Hook for psbObj in rsvp_softstate */
   void *rsbObj; /* Hook for rsbObj in rsvp_softstate */

   /* Pointer to hash lists of PSB/RSB interface as key */
   void *psb_hash_if_as_key;
   void *rsb_hash_if_as_key;
  
   /*-----------------------------------------------------------------
    * Holder for all tunnels data structure. Tunnel Interface that is   
    * configured would be maintained at this data structure by rsvpd.c
    * module. These are organized in a AVL tree.
    *----------------------------------------------------------------*/
   void* tunnel_if_Obj;

   /*-----------------------------------------------------------------
    * Following are maintained by mpls_lsp module
    *----------------------------------------------------------------*/
   /* Global Object handle for all MPLS LSPs in the Daemon */
   void *lspObj;
   /* Hash of lsps with ifindex as key */
   void *lsp_hash_if_as_key;

   /*-----------------------------------------------------------------
    * I/O Facilities for the daemon 
    *----------------------------------------------------------------*/
   /* Socket handle for Reading/Writing packets with external world */
   int sock;
   struct thread *t_read;
   struct thread *t_write;
   /* Interfaces queued for reading and writing */
   struct list *rsvp_if_write_q;

   char *name;

   /* Hook for Label Manager */
   struct rsvp_label_mgr *label_mgr;
   /* Hook for Routing Table */
   struct rsvp_rtable *rtable;

   /* Statistics Data */
   struct rsvp_statistics statistics;
};


/* This Data Structure Holds all info on a configured ingress Tunnel
   Interfaces. As they are virtual interfaces so needs to be maintained
   separately then "struct interface". The CLI gets a consistemt view
   of tunnel as an interface. An interface is NOT a LSP. It's a traffic
   trunk (RFC 2702). A Tunnel can have one or more LSPs. It will point 
   to the LSP Objects. At present we don't support load balancing of 
   of the Tunnel over multiple LSPs. So only one LSP would be active */
   Tunnel Interaces are organized in a AVL tree and hooked into 
   rsvp->tunnel_if_obj. */
 
struct rsvp_tunnel_if
{
   /* The Tunnel Type */
   int type; 
   /* Tunnel Status */
   int status;
   struct in_addr dst_addr;
   /* List of RSVP LSPs for this Tunnel, only one active*/
   struct list *rsvp_lsp_list;
};

/* This Data Structure Holds all info on a egress tunnel */

RSVP_PROTO_VERSION	1
RSVP_MSG_MAX_LEN	65535
RSVP_IP_PROTO		46 /* As per RFC 2205 */

RSVP_TUNNEL_TYPE_INGRESS	1
RSVP_TUNNEL_TYPE_EGRESS		2
RSVP_TUNNEL_TYPE_TRANSIT	3




RSVP Peer Structure
========================
This defines a RSVP peer/neighbor, This is used to contain all info on a RSVP neigbors. Note that a neighbor is different then interface (struct rsvp_if). Multiple neighbors can be accessed through the same rsvp_if
if the interface connects to a broadcast/multi-access network such as a bridge. in RSVP, a rsvp_peer or neighborship is not formed explicitly.

A peer is added by rsvp_softstate module when 

1)A rsvp_path_msg is received that causes to add a "new" rsvp_psb from 
  peer (as phop) and that phop doesn't exist in object that contains 
  all the peers. This could be achieved by searching the global object 
  of rsvp_peers with phop as key. If not found then create a rsvp_peer    
  and initialize parameters as received from the message and increment 
  rsvp_peer->ref_cnt by 1.If found then update the peer info received 
  from the message and rsvp_peer->ref_cnt by 1.
  
2)Add a rsvp_psb to peer (as nhop)and that nhop doesn't exist
  in object that contains all the peers. This could be achieved 
  by searching the global object of rsvp_peers with nhop as key. 
  If found then increment the rsvp_peer->ref_cnt by 1.


NOTE : We wouldn't have to take rsvp_rsb as consideration for a peer creation because a rsvp_rsb is considered valid ONLY when a corresponding rsvp_psb is established. In that case the rsvp_psb might have already installed the rsvp_peer. So a rsvp_peer is referred when we have either we have rsvp_psb(s) installed from the peer or we have rsvp_psb(s) installed to the peer.

But this is not a valid case always. There could be certain    
situations where a rsvp_psb might be deleted due to path tear or 
path err, but the rsvp_rsb is not deleted because either resv_tear 
or path_tear is got lost.In that case  we need to take care of 
rsvp_rsb also that would still be referring to teh rsvp_peer.

3) Add a "new" rsvp_rsb from peer(phop). Search the peers with phop as 
   key. If not found create a new rsvp_peer and initialize to all 
   parameters received in the rsvp_resv_msg. If found son't create
   but increment the rsvp_peer->ref_cnt

4)Do the same as 3 for rsvp_rsb->nhop.   
 
A peer is deleted by rsvp_softstate module when we

1) delete a rsvp_psb from and that is the last rsvp_psb that refers
   to the peer as phop. To implement this search the global rsvp_psb 
   object with key as phop. If the peer not found then assert(0) as its
   not a valid condition. If found decrement the rsvp_peer->ref_cnt by 
   1 and check if that makes rsvp_peer->ref_cnt = 0. If yes, then '   
   delete rsvp_peer completely.

2) Repeat the same for rsvp_psb->nhop. Search peer with nhop as key and
   delete the peer if this was the last reference.

3) Delete a rsvp_rsb. Check the peer matching the rsvp_rsb->nhop.
   If the peer not found then do assert(0) because peer must exist.
   Decrement the rsvp_peer->ref_cnt by 1 and check if that makes
   rsvp_peer->ref_cnt = 0. If yes then delete the rsvp_peer.

4) Do the same as 3) for rsvp_psb->nhop.

So what information should we keep in a rsvp_peer ?

/* Struct that defines a rsvp peer. All peers are organized in a AVL Tree. Peer search has to be done for each path/resv message and so the search has to be efficient. Note that rsvp_peer doesn't mean that its
is RSVP capable.*/

struct rsvp_peer
{
   /* This is the total number of PSB or RSBs that references this peer
      as either next hop or previous hop. I think 2^32 is sufficient 
      number for accomodating the total psb/rsbs
    */
   u_int32_t ref_cnt;
   /* Capability/config flags. */
   u_int32_t cflags;
#define RSVP_PEER_CFLAG_RSVP(1 << 0)  /* RSVP Capable Node. */
#define RSVP_PEER_CFLAG_GR  (1 << 1)  /* Graceful Restart Capable.*/
#define RSVP_PEER_CFLAG_RR  (1 << 2)  /* Refresh Reduction (RFC 2961)*/
#define RSVP_PEER_CFLAG_RD  (1 << 3)  /* RSP Reliable Delivery. */

   /* Address of the peer. This is NOT the loopback address of the rsvp 
      capable neigbor router, rather a IP interface address. A peer is 
      nothing but a neighbor hop.*/ 
   in_addr addr;

  /* Bundle Trigger Timer. This timer shouldn't be user 
     configurable, but hardcoded in implementation. When this timer 
     triggers all messages in the bundle_trigger_msg_queue are flushed 
     with single bundle message. The timer is active only when this 
     rsvp_peer is set for Refresh Reduction (RR) */
   struct thread *t_bundle_trigger_msg_timer;

   /* Bundle Refresh Timer: This timer too shouldn't be user 
      configurable. This timer flushes the bundle_refresh_msg_queue*/
   struct thread *t_bundle_refresh_msg_timer;

 /* Messages enqueued for bundling to this peer. So whenever we have
    Trigger messages to send to a peer which is RFC 2961 capable we 
    enqueue packets in this queue. The timer fires within some n 
    seconds and sends all packets from the queue in the bundle */
    struct list *bundle_trigger_msg_queue;

/* Refresh messages enqueued for bundling in this queue. This queue is 
   flushed when t_bundle_refresh_msg_timer fires. */   
    struct list *bundle_refresh_msg_queue;                 
}



rsvpd.c
=========
/* The RSVP Tunnel APIs */

The following handler triggers a RSVP Tunnel Creation.
rsvp_interface_tunnel_cmd
          |
          v (Create a new Tunnel Data Structure and put it in AVL Tree 
             with Key as Tunnel Number) 
   struct rsvp_tunnel_if *rsvp_create_tunnel_if(int num)
          |
          v
   Set the flag as "INCOMPLETE_CONFIG". 
   rsvp_tunnel_if_set_config_incomplete(struct rsvp_if *);
          |
          v
   by default the Tunnel Interface is admin up. 
   rsvp_tunnel_if_admin_up (struct rsvp_tunnel_if *); 

NOTE: The mimimum parameter for making a config complete is at least
      one path element and tunnel destination is configured.

When a Tunnel mode parameters is put from CLI, then fill the corresponding
param. in struct rsvp_tunnel_if and check if config is complete to 
start the tunnel.
          |
          v
   rsvp_tunnel_if_set_config_complete (struct rsvp_if *);
          |
          v
   rsvp_tunnel_if_is_config_complete (struct rsvp_if *);
          |
          v
   Then start the tunnel - rsvp_tunnel_if_start (struct rsvp_tunnel_if *);

The following event happens when a Tunnel is started.

rsvp_tunnel_if_start procedures
=========================
1) Check the tunnel path options and create rsvp_lsps (rsvp_lsp_create) one by 
   one for each path in the 6 element array. Initialize parameters on each LSP.
   from the configured parameters in the rsvp_ip_path and rsvp_if_tunnel.
   rsvp_lsp has visibility only upto path_option and not the rsvp_if_tunnel.
   So all relevant parameters in rsvp_lsp will be set up at the time of 
   creation by this procedure.

2) This in turn calls on the corresponding rsvp_lsp.
   rsvp_lsp_start(struct rsvp_ldp *). This starts RSVP Signaling for the
   lsp.

rsvp_lsp_start event procedure
==============================
3) Check if the destination in the rsvp_if_tunnel is reachable by IGP routing.
   If yes, proceed. Else, set the LSPs flag as down due to NO_ROUTE and 
   start retry_timer of the LSP.
4) Check if CSPF is set on the LSP. If yes, calculate CSPF and get the best 
   source route. 
5) If the parent rsvp_path_option is dynamic then take the CSPF path and 
   compute ERO and proceed. If path is strict the compare the map of explicit 
   path. If matches then take the path map into ERO and proceed. If no CSPF
   and dynamic then follow best effort path.
6) Create and initialize a rsvp_lsp corresponding to the path option and hook 
   the handle into the rsvp_tunnel_if_path_option. Hook the corresponding
   rsvp_tunnel_if_path_option into rsvp_lsp->ingress_user_handle.
   Hook the rsvp_lsp into the global handle of ingress LSPs.
7) Install the corresponding PSB in softstate module(rsvp_softstate_create_psb)
   and send path message through the corresponding interface to the 
   corresponding neighbor and return.Go to exit.
 
rsvp_lsp_ingress_up() event procedure
===========================    
 
1) This is called by RSVP LSP module if a rsvp_lsp that is ingress in this 
   router is UP. The argument is the rsvp_ip_path_option_handle 
   (rsvp_lsp->rsvp_ip_path_option_handle). This in turn invokes 
   rsvp_tunnel_if_path_option_event (LSP_UP, struct rsvp_tunnel_if_path_option).
2) This handler looks up if active_path_option = 0. If yes, it sets
   path_option_number as active_path_option. If active_path is already 
   set then do nothing.

rsvp_lsp_ingress_down() event procedure
=======================================

1) Check if the down LSP is active at present. If yes go to step 2
2) Search for alternate UP lsp for active.
   rsvp_tunnel_if_path_option_set_active (struct rsvp_tunnel_if *). If no
   active path_option found having lsp up, then it sets the Tunnel as down.

APIs for rsvp_tunnel_if
=======================
struct rsvp_tunnel_if *rsvp_tunnel_if_create (int num);
void RSVP_TUNNEL_IF_SET_INCOMPLETE (struct rsvp_tunnel_if *); /* MACROS. */
void RSVP_TUNNEL_IF_SET_COMPLETE (struct rsvp_tunnel_if *);   /* MACROS. */
int rsvp_tunnel_if_is_config_complete (struct rsvp_tunnel_if *);
int rsvp_tunnel_if_start (struct rsvp_tunnel_if *);
int rsvp_tunnel_if_stop  (struct rsvp_tunnel_if *);
int rsvp_tunnel_if_restart (struct rsvp_tunnel_if *);
int rsvp_tunnel_if_switch_lsp (struct rsvp_tunnel_if *, int path_option);
void rsvp_tunnel_if_admin_up (struct rsvp_tunnel_if *);
void rsvp_tunnel_if_admin_down (struct rsvp_tunnel_if *);
void rsvp_tunnel_if_set_dst (struct rsvp_tunnel_if *, struct prefix *);
void rsvp_tunnel_if_unset_dst (struct rsvp_tunnel_if *);
void rsvp_tunnel_if_set_path (struct rsvp_tunnel_if *, 
                              int pathnum, type); 
void rsvp_tunnel_if_unset_path (struct rsvp_tunnel_if *, int pathnum); 


Timers
The refresh timer per rsvp_if is fired for each hello interval.

/* This API starts hello timer on this RSVP Interface */
rsvp_if_hello_start (struct rsvp_if *)
{
   RSVP_THREAD_ON (rsvp_if, rsvp_hello_timer_expired);
}

rsvp_if_hello_stop (struct rsvp_if *)
{
   RSVP_THREAD_OFF (rsvp_if->hello_timer);
}

rsvp_if_hello_restart (struct rsvp_if *)
{
   RSVP_THREAD_OFF (rsvp_if->hello_timer);
   RSVP_THREAD_ON  (rsvp_if->hello_timer);
}

void rsvp_if_hello_timer_expired (struct thread *)
{
  The thread argument is struct rsvp_if *.
  Actions:
  1.Send out Hello over the rsvp_if
    Call rsvp_packet_send_hello (struct rsvp_if *).
    It allocates a stream and call 2.
  2. This in turn calls 
    rsvp_packet_add_to_if (struct stream *s, struct rsvp_if *).
    This API adds the stream to rsvp_if->o_buf.
  3. Enable RSVP WRITE Thread.
    RSVP_WRITE_ON (rsvp_if->fd, rsvp_packet_write, rsvp_if->obuf);

  4. The packet will be written into the file descriptor maintained 
    for the rsvp_if. 
    rsvp_packet_write(struct thread *);
    The thread arg is struct rsvp_if
    The thread value is fd (struct rsvp_if->fd);
    rsvp_packet_delete_from_if (struct rsvp_if *);
}   

RSVP LSP MODULE
================
This is the upper level module taht provides the abstraction of a MPLS LSP
to the user. The CLI module interacts with this module. There are two levels
of abstraction provided by this module- rsvp_tunnel and rsvp_lsp. Note that
struct rsvp_tunnel here is different then the rsvp_tunnel_if defined in
rsvpd.c. The reason is that rsvp_tunnel_if is administratively created with
configuration info at the ingress LSR only. rsvp_tunnel is an abstraction that
identifies any tunnel as per RFC 2702. And a Tunnel may have one or more LSPs.
so rsvp_lsp is child of rsvp_tunnel.


So the abstractions are organized in the following levels.

                struct rsvp_tunnel_if (config infos)
                          |
                struct rsvp_tunnel (Dynamically created from the config info).
                    /           \  
                   /             \ 
               rsvp_lsp        rsvp_lsp
                 |                |
               struct psb      struct psb

So, the common output "show mpls traffic-emg tunne" shows all rsvp_tunnels.

The RSVP LSPs are described by struct rsvp_lsp and is common for all types of 
LSPs. An LSP type can be ingress LSP, Transit LSP or can be an Egress LSP. 
PSB/RSBs are tightly coupled with LSP data structure "indirectly" as an active 
PSB and its corresponding RSB makes a LSP active. "Indirectly" means LSP has no clue abou interval PSB/RSB structs, but exchanges info through struct rsvp_psb_info/rsvp_rsb_info with rsvp_softstate module through callbacks. This is an 
event based module. RSVP Softstate module will generate events per PSB/RSB basis and this module will extract info for create/update/delete LSPs from the struct rsvp_psb_info/rsvp_rsb_info.Then this module will interact with LSP FSM for each event and do handle necessary action.

This module further interacts with zMPLS daemon for add/del/modify LSP and 
add/del tunnels.

rsvp_lsp.h
===========

RSVP_LSP_TYPE_INGRESS
RSVP_LSP_TYPE_EGRESS
RSVP_LSP_TYPE_TRANSIT

A RSVP TE-LSP goes through the following states.
RSVP_LSP_STATUS_DOWN /* LSP is down due to signaling failure (Ingress) */
RSVP_LSP_STATUS_DOWN_RETRY_EXPIRED /* LSP is down because retry count 
                                      reached max (Only for ingress)
RSVP_LSP_STATUS_UP    /* LSP is up and active, both PSB/RSB installed*/
RSVP_LSP_STATUS_PSB_ACTIVE /* Only PSB Installed */
RSVP_LSP_STATUS_MBB   /* Make Before Break is going ON */
RSVP_LSP_STATUS_CSPF  /* CSPF Computatation is going on (Only ingress) */ 

typedef enum
{
   RSVP_LSP_STATUS_DOWN,
   RSVP_LSP_STATUS_DOWN_STANDBY,
   RSVP_LSP_STATUS_UP,
   RSVP_LSP_STATUS_..
   ...

}rsvp_lsp_status_t;

/* The RSVP LSP Descriptor */
struct rsvp_lsp
{
   /* The LSP Type, INGRESS, TRANSIT or EGRESS */
   int type;
   rsvp_lsp_status_t status;

   /* Info extracted from PSB/RSB */
   int l3pid;
   union 
   {
      struct in_addr lsp_ipv4_src_addr;
      struct in6_addr lsp_ipv6_src_addr;
   }u1;
#define lsp_ipv4_src_addr u1.lsp_ipv4_src_addr
#define lsp_ipv6_src_addr u1.lsp_ipv6_src_addr

   union 
   {
      struct in_addr lsp_ipv4_dst_addr;
      struct in6_addr lsp_ipv6_dst_addr;
   }u2;
#define lsp_ipv4_dst_addr u2.lsp_ipv4_dst_addr
#define lsp_ipv6_dst_addr u2.lsp_ipv6_dst_addr

   u_int16_t tunnel_id;
   u_int16_t lsp_id;

   union
   {
      u_int32_t lsp_ipv4_ext_tunnel_id;
      u_int32_t lsp_ipv6_ext_tunnel_id;
   }u3;
#define lsp_ipv4_ext_tunnel_id u3.lsp_ipv4_ext_tunnel_id
#define lsp_ipv6_ext_tunnel_id u3.lsp_ipv6_ext_tunnel_id

   /* Timer threads for this LSP. Take the values from
      struct rsvp */  
   struct thread *t_retry_timer;/* Active when lsp id down except
                                   DOWN_STANDBY state */
   struct thread *t_reopt_timer;
   u_int32_t retry_count; 

   /* The Upstream Interface and Label for this LSP */
   int ifindex_up;
   u_int32_t label_up;
 
   /* Downstream Interface and Label received*/
   int ifindex_dn;
   u_int32_t label_dn;

   time_t uptime;

   /* Hooks to PSB/RSBs for this LSP */
   void *psb_handle;
   void *rsb_handle;
};

rsvp_lsp structure organization :

The rsvp_lsp structure is organized as a groups to the same src_addr.
Each group further sparses the rsvp_lsps based on Tunnel IDs.

The organization is made globally. 

Apart from that lsps are organized in hash list with if_index as key.

struct rsvp_lsp *rsvp_lsp_create ();
int rsvp_lsp_start  (struct rsvp_lsp *);
int rsvp_lsp_stop   (struct rsvp_lsp *);
int rsvp_lsp_reoptimize (struct rsvp_lsp *);
void rsvp_lsp_event_handle (struct rsvp_lsp *, int event);

Following APIs needed and Pseudocodes are as follows: 
These are timer handlers.

rsvp_psb_expired (struct thread *)
{
   thread argument is struct rsvp_lsp for which the rsvp_psb is timed 
   out.
   Actions
   1.delete the psb
   2. 
   2.Send reservation error for psb 
}

rsvp_rsb_expired (struct thread *)  
{
   thread argument in struct rsvp_lsp for which the rsvp_rsb is timed 
   out. 
   1. delete the rsb
   2. 
}

RSVP_LSP_FSM module
====================
rsvp_lsp_fsm.h

LSP Events


rsvp_lsp_fsm.c
==============
struct 
{
   int (*func)();
   int next_state;
} RSVP_LSP_FSM [RSVP_LSP_STATUS_MAX -1][RSVP_LSP_EVENTS_MAX-1] = 
{


}

MPLS Tunnel Module
==================


mpls_tunnel.h
====================================
#define MAX_LSP_PER_TUNNEL      6
#define TUNNEL_NAME_LEN         128

typedef enum
{
   RSVP_TUNNEL_INGRESS = 1,
   RSVP_TUNNEL_TRANSIT = 2,
   RSVP_TUNNEL_EGRESS  = 3
} rsvp_tunnel_type_t;

struct rsvp_tunnel
{
   char               name [TUNNEL_NAME_LEN];
   rsvp_tunnel_type_t type;
   u_int132_t         if_num;  /* Interface numbers are type specific.*/
   struct in_addr     dst;     /* Destination of the Tunnel.*/
   u_char             status_admin;
   u_char             status_oper;

   u_char             up_lsps;
   struct rsvp_lsp    rsvp_lsp [MAX_LSP_PER_TUNNEL];
};

RSVP Tunnel Organization :

rsvp_tunnels are organized as ingress, egress and transit tunnels.

For ingress tunnels the sender_addr is fixed. The keys that signify diff
tunnels are dst_addr, the tunnel number (inherited from rsvp_tunnel_if *).

For egress tunnels the dst_addr are fixed (The LSR Router address).
The search keys are sender_addr.

For transit tunnels the keys the first level is src_addr, 

/* Tunnel Level Abstractions */

struct rsvp_tunnel *
rvsp_tunnel_create ();

int
rsvp_tunnel_delete (struct rsvp_tunnel *);

int
rsvp_tunnel_add_lsp (struct rsvp_tunnel *,
                     struct rsvp_lsp *);

int
rsvp_tunnel_delete_lsp (struct rsvp_tunnel *,
                        struct rsvp_ldp *);

int
rsvp_tunnel_start (struct rsvp_tunnel *);

int
rsvp_tunnel_stop (struct rsvp_tunnel *);

int
rsvp_tunnel_dump_vty (struct rsvp_tunnel *);


 

RSVP Interfaces
================
rsvp_if.h
/*
RSVP Interface is private data structure hooked into struct interface->data. RSVP Sessions with neighbors are mainatined by RSVP Interfaces. The RSVP Interface(struct interface->rsvp_if)is enabled when a physical interface is enabled administratively for RSVP from CLI. Basic criteria for making at active is that it should be at an IP interface, If IP is not configured then although RSVP is enabled , still keep the rsvp_if as INACTIVE. This data structure needs to be created during rsvp_if_init which is called suring stack initialization. If at least one valid session is found then we set session_exist flag to 1.Then we need to maintain hellos on that interface for maitenance/refresh of PSB/RSB. */

/*---------------------------------
 * Status of RSVP on  a Interface 
 *--------------------------------*/
enum 
{
   RSVP_IF_DOWN = 0, /* Down due to parent struct interface is down. */
   RSVP_IF_DOWN_NO_IP = 1, /* Down due to no IP is configured */
   RSVP_IF_UP  = 2         /* UP and ready for running RSVP Sessions */
}rsvp_if_status;

struct rsvp_if
{
   int status;
   /* Back Pointers */
   struct rsvp *rsvp;
   struct interface *if;

   /* The Packet Queue for writing */
   struct rsvp_packet_fifo *obuf;

   /* The Hello Timer Thread */
   struct thread *t_hello_timer;

   /* Number of sessions (or LSPs) */
   int session_nums;

   /* RSVP Interface specific statistics */
   struct rsvp_statistics statistics;
  ...
}

Interface Events
================
RSVP_IF_DOWN
RSVP_IF_UP
RSVP_IF_ADD
RSVP_IF_DEL

rsvp_if.c
=========
/* Handles events from interface layer. */
rsvp_if_event_handle (int event);


RSVP Packet Processing Module
==============================
The RSVP Packet Processing Module provides all packet processing utilities
required by the Daemon. This module uses the utility services provided by
rsvp_obj module for analyzing/creating a packet and futher interacts with
rsvp_softstate module for updating/creating/deleting psb/rsb. This module
interacts with rsvp_network module for sending/receiving packets.

rsvp_packet.h 

/* RSVP Path Message to be supported in Phase 1 */

+--------------------------------------------------+
| RSVP Message Common Header                       |
+--------------------------------------------------+
| SESSION OBJECT                                   |
+--------------------------------------------------+
| RSVP HOP                                         |
+--------------------------------------------------+
| Time Values                                      |
+--------------------------------------------------+
| Label Request                                    |
+--------------------------------------------------+
| Sender Template                                  |
+--------------------------------------------------+
| Sender Tspec                                     |
+--------------------------------------------------+

/* RSVP Resv Message to be supported in Phase 1 */

+---------------------------------------------------+
| RSVP Message Common Header                        |
+---------------------------------------------------+
| RSVP Session                                      |
+---------------------------------------------------+
| RSVP_HOP                                          |
+---------------------------------------------------+
| TIME_VALUES                                       |
+---------------------------------------------------+
| STYLE                                             |
+---------------------------------------------------+
| Flow Descriptor List                              |
+---------------------------------------------------+



/*-----------------------------------
 * The Generic RSVP Packet Descriptor
 * used only for sending packets. This is the 
 * format in which rsvp_packet module 
 * interacts with rsvp_network module
 *----------------------------------*/
struct rsvp_packet
{
   int flag;
#define RSVP_PACKET_IPHDR   ( 1 << 0) /* If valid IP Header is included in the 
                                         stream*/
#define RSVP_PACKET_RA      ( 1 << 1) /* If Router Alert is to be set for this
                                         packet. */   
   struct rsvp_packet *next;

   /* Path messages always carry at upper levels.*/
   struct ip ip_hdr;
   /* Pointer to data stream */
   struct stream *s;

   /* Next hop of the RSVP Packet. */
   struct in_addr dst;

   /* RSVP Packet Length */
   u_int16_t length; 
};

/*------------------------------------
 * RSVP Packet Queue Structure used for
 * sending packets.
 *-----------------------------------*/
struct rsvp_packet_fifo
{
   unsigned long count;
   struct rsvp_packet *head;
   struct rsvp_packet *tail;
};

/* The Header template for a RSVP Message */
struct rsvp_msg_hdr
{
   u_char vers 4;
   u_char flags 4; 
   rsvp_msg_type_t type;
   u_int16_t checksum;
   u_char send_ttl;
   u_char reserved;
   u_char rsvp_length;
};
RSVP_MSG_TYPE_PATH	1
RSVP_MSG_TYPE_RESV	2
RSVP_MSG_TYPE_PATHERR	3
RSVP_MSG_TYPE_RESV_ERR  4
RSVP_MSG_TYPE_PATHTEAR	5
RSVP_MSG_TYPE_RESVTEAR	6
RSVP_MSG_TYPE_RESVCONF	7

typedef enum 
{
   RSVP_MSG_TYPE_PATH,
   RSVP_MSG_TYPE_RESV
   RSVP_MSG_TYPE_PATHERR,
   RSVP_MSG_TYPE_RESV_ERR
   RSVP_MSG_TYPE_PATHTEAR,
   RSVP_MSG_TYPE_RESVTEAR,
   RSVP_MSG_TYPE_RESVCONF,
   RSVP_MSG_TYPE_HELLO,
   /* RFC 2961 Extensions. */
   RSVP_MSG_TYPE_BUNDLE
}rsvp_msg_type_t;  

rsvp_packet.c
=============

The RSVP Packet module is again divided into 2 layers. 

   Set of APIs deal with only RSVP specific messages. This layer communicates
   a packet with the lower layer through struct rsvp_packet that contains the 
   complete  RSVP message/bundle message (RFC 2961).
  
One basic assumption is :

A. Path messages when received are manipulated in rsvp parameters only. IP
   Header remains intact (it's end to end). So neither path_msg nor ip_hdr
   is destroyed.Path message must be sent with ip src hdr same as in 
   SENDER_TEMPLATE and dst_addr must be the same as in SESSION. 

B. Resv messages when received are stripped of ip header and then manipulated 
   in rsvp parameters. So rsv_msg can't be destroyed, but ip_hdr is and a new
   ip_hdr is put when sending out the resv_msg.

So path/resv msgs are never destroyed in transit . Path msg is destoyed
in egress and resv msg in ingress ONLY.

1) NOTE : We process only MPLS-RSVP Path Messages. In phase 1 we are
          supporting on mandatory params.
   rsvp_packet_path_receive (struct rsvp_msg_hdr *,
                             struct rsvp_packet *,
                             struct rsvp_if *)
  {
     1. If INTEGRITY Object is present immediately after common header. If 
        integrity fails then drop the message.
     2. When SESSION Object is found, Check if ctype == LSP_IPV4/LSP_IPV6
        else return Path Err.
        extract the session_info like
        session_info->tunnel_id
        session_info->destination.

        rsvp_obj_decode_session (struct stream *s, size);

     3. Look for SENDER_TEMPLATE and extract the info
        Check if C-TYPE is LSP_IPV4/LSP_IPV6. If not return path_err

        rsvp_obj_decode_sender_template (struct stream *s, size);       
       
     4.
        Lookup the PSB in alreay installed in system (that will determine
        whether its a refresh or trigger message. The key to search a PSB 
        are those ones that doesn't change throughout the session.

        struct rsvp_psb *rsvp_softstate_lookup_psb (tunnel_id, lsp_id,
                                                    source_addr, dst_addr);
     5. If the PSB is not found then create a new PSB.
        struct rsvp_psb rsvp_softstate_install_psb (..)
        Fill all necessary parameters. 
        Record rsvp_psb->phop from that obtained from the message and check
        that rsvp_peer with that addr exist. If yes.. Record the rsvp_psb->ifindex_up.
        Install Label Request Object.
        Install timer as per TIME Values.
        start the rsvp_psb->cleanup_timer.
        start the rsvp_psb->refresh_timer.

     6. If existing PSB then reset the rsvp_psb->t_cleanup_timer.
     7. Update the PSB with changed parameters if any.
     8. Check if the destination of IP packet is itself. If yes, that means
        this is the egress of the session and match the dst_addr in SESSION
        is same as IP header dst addr(section 3.1.3 in RFC 2205).If yes then 
        install RSB and initiate resv_message to the source else returns path
        error. If destination is self. Else go to 9.
     9. If NO ERO present then check with routing the outgoing interface(ifp)
        and nhop. 
        rsvp_route_lookup_ipv4 (struct rsvp_rtable, in_addr dst);  
        If ERO is present then lookup the route based on dst ar ERO next hop.
         
     9. Set the PHOP in the existing path message to the address of the
        interface (ifp->connected).
     10.Send the packet to the next_hop and addr.
        rsvp_packet->dst_addr = nhop.
        add the packet to the rsvp_if.
        rsvp_packet_add_to_if (rsvp_packet, rsvp_if);
     11. Start the thread rsvp_write.
  }

2)
   rsvp_packet_resv_receive (struct rsvp_packet *,
                             int ifindex)
   {
    
      1) Check for the matching rsvp_psb. If not found drop and free the
         packet memory. Else go to step 2.
      2) Check if  the rsvp_rsb pointed by the matched rsvp_psb exists. If yes
         go to 3) else go to 4.
      3) Check if all rsb parameters are same as that of in resv msg. 
         Else update it and reset the rsvp_rsb cleanout timer.
      4) Check that ifindex == rsvp_psb->next_hop. If yes, the install rsb
         and start cleanout time. Else drop the message and free the buffer.
      5) Don't destroy, rather send the same resv_msg with a new IP header
         with this node as src_addr and rsvp_psb->phop as dst_addr.
         
         rsvp_resv_msg_snd (struct rsvp_packet *,
                            int rsvp_psb->phop);
   } 
      
3) The lower below deals with all communication with RAW/IP layer and 
   provides a generic interface to all packets through struct rsvp_packet
   and interacts with rsvp_network layer.


1. /* Generic Utilities for Creating and destroying a RSVP Packet used for  
   sending */
rsvp_packet_new (size_t size);
rsvp_packet_free (struct rsvp_packet *);

2. The generic Send and Receive Hnadles on RSVP Interfaces are as follows. These thread handlers are the lowest level APIs that interact at socket level 
 through the APIs provided by rsvp_network module. 

   Let's see what are the assumptions in RFC 2205/RFC 3209 in send/receive of 
   RSVP messages.

   1) At ingress IP src/dst fields would be filled by RSVP for path msgs.
      At transit IP src/dst fileds would remain same
      At egress/transit the IP src/dst fields would be decided based on phops
      in psbs for resv msgs
      So, IP_HDINCL option needs to be set on the socket used for RSVP.

   1) At ingress when NO_CSPF and NO_ERO is used then path message ie sent via 
      best effort path by looking up outgoing interface/next hop in routing 
      table.For that rsvp needs routes from zebra and refer to rsvp->rtable.
      So the API needs to take src_addr, dst_addr, the rsvp specific packet
      in stream, next hop and outgoing ifindex.

      At ingress if CSPF/ERO is used then there is no direct lookup in the 
      routing table. ERO already sets the nexthop and the first hop is the
      outgoing interface address (and if can be found). Second hop is the 
      next hop. So the API is needed to take src_addr, dst_addr, stream, next
      hop and outgoing if.

      At transit, after receiving a path msg we need to preserve the IP
      Header.  

      /* This returns a stream with ip header included.*/
      struct stream *rsvp_packet_recv (rsvp->fd, struct interface *);

      rsvp_packet_send (struct stream *s,
                        struct in_addr *src_addr,
                        struct in_addr *dst_addr, 
                        struct rsvp_peer *next_hop,
                        int ifindex);
                                          
   
   2.1 rsvp_packet_read (struct thread *);
       Reads a packet from the rsvp->fd. The starting point of receive
       processing.
 
   2.2 rsvp_packet_write (struct thread *);
       The Final point of packet writing. This is a thread function
       with THREAD_ARG as struct rsvp*. 
       2.2.1 This procedure gets rsvp->fd for writing and 
             rsvp->rsvp_if_write_q, the queue of rsvp_if(s)
             which are enqueued for writing. 
       2.2.2 We get the 1st rsvp_if(s) and get the first packet its 
             stream_fifo. The packet will be 
       2.2.3 
If further packets in 
       stream_fifo exists or another rsvp_if exists in 
       rsvp->rsvp_if_write_q then we make the LDP_WRITE_ON.  


2. Generic Utilities for adding and deleting s stream to/from 
   struct rsvp_if and inserting msg_hdr

/* Decoder of rsvp message header. This API extracts the RSVP Message 
   Header from stream->getp and fills up the struct rsvp_msg_hdr
   passed on y the caller */
void
rsvp_packet_decode_msg_hdr (struct stream *s,
                            struct rsvp_msg_hdr *msg_hdr);


/* Creator of the Msg Header. The message header is created at the  
   the location of putp*/
void
rsvp_packet_encode_msg_hdr (struct stream *s, 
                            u_char ver, 
                            u_char flags,
                            rsvp_msg_type_t msg_type,
                            u_int16_t checksum,
                            u_char send_ttl,
                            u_char reserved,
                            u_int16_t length);

/* This API computes the checksum of the RSVP Message
   that starts at msg_startp and ends at stream->putp.
   The reason of msg_startp is that when RSVP Message 
   bundling is used later then one stream MAY contain
   multiple messages. The checksum value will be  
   computed ans inserted into the checksu field in the
   message header*/
void
rsvp_packet_encode_msg_checksum (struct stream *s,
                                 int msg_startp);

/* This API calculates the length of the message from startp
   and stream->putp and inserts into the length field in msg_hdr
 */ 
void
rsvp_packet_encode_msg_length (struct stream *s,
                               int msg_startp);
                                 

/* In the first version, I am going to send only mandatory params in each
   message. *.

void
rsvp_packet_encode_path_msg (struct stream *,
                             struct session_info *;
                             struct rsvp_hop_info *,
                             struct rsvp_timevalues_info *,
                             struct sender_template_info *,
                             struct sender_tspec_info *); 


/* Adds/Deletes a RSVP Packet to/from rsvp_if->obuf */
void
rsvp_packet_add_to_if (struct stream *s,
                       struct rsvp_if *);
rsvp_packet_del_from_if (struct rsvp_if *);

3. The message specific handlers called by the handlers in 1 for specific messages.  

/* The Generic Message Sender
 * Inputs : s = stream to send
 *          src_addr = Source Address of the Packet 
 *          dst_addr = Destination Address of the Packet
 *           
 */
rsvp_packet_send_msg (struct stream *s,
                      struct in_addr *src_addr,
                      struct in_addr *dst_addr, 
                      struct interface *rsvp_if);
rsvp_packet_receive_path_msg (struct stream *s, struct rsvp_if *rsvp_if);

/* 
rsvp_packet_send_resv_msg (struct rsvp_packet *rsvp_packet, 
                           struct rsvp_if *rsvp_if,
                           struct in_addr *hop)
rsvp_packet_receive_resv_msg (struct stream *s, struct rsvp_if *rsvp_if);
rsvp_packet_send_path_err (struct stream *s, struct rsvp_intf_mgr *intf_mgr);
rsvp_packet_receive_path_err (struct stream *s, struct rsvp_intf_mgr *intf_mgr);
rsvp_packet_send_path_tear (struct stream *s, struct rsvp_intf_mgr *intf_mgr);

4. RSVP Message Parser 

rsvp_packet_decode_msg_hdr (struct stream *s, struct rsvp_msg_hdr *hdr)


4. RSVP network Module
=======================
This module provides all interaction necessary for RSVPD communication with
the network. This module sends/receives rsvp packets to/from network. This
module provides services to the rsvp_packet module. So all APIs (abstractions)
provided by this module is aligned with services required from rsvp_packet
module.

int
rsvp_sock_init (void)
{


} 

5. RSVP Object Processing Module
==============================
This module is library for processing the following objects and class types. 
LSP_TUNNEL_IPV4
LSP_TUNNEL_IPV6
LABEL_REQUEST
LABEL
EXPLICIT_ROUTE
RECORD_ROUTE
SESSION_ATTRIBUTE

C-types : SESSION, SENDER_TEMPLATE and FILTER_SPEC

rsvp_obj.h

RSVP_OBJ_LEN_MAX	65528
RSVP_OBJ_LEN_MIN	4



RSVP_CLASS_NULL		                       0

RSVP_CLASS_SESSION	                       1
RSVP_CLASS_SESSION_CTYPE_IPV4_UDP 	           1
RSVP_CLASS_SESSION_CTYPE_IPV6_UDP		     2
/* RFC 3209 RSVP-TE Extensions */
RSVP_CLASS_SESSION_CTYPE_LSP_TUNNEL_IPV4       7
RSVP_CLASS_SESSION_CTYPE_LSP_TUNNEL_IPV6       8

RSVP_CLASS_RSVP_HOP				     3
RSVP_CLASS_RSVP_HOP_CTYPE_IPV4                 1
RSVP_CLASS_RSVP_HOP_CTYPE_IPV6                 2

RSVP_CLASS_INTEGRITY				     4
		
RSVP_CLASS_TIME_VALUES                         5
RSVP_CLASS_TIME_VALUES_CTYPE	                 1

RSVP_CLASS_ERROR_SPEC	                       6
RSVP_CLASS_ERROR_SPEC_CTYPE_IPV4	           1
RSVP_CLASS_ERROR_SPEC_CTYPE_IPV6               2 

RSVP_CLASS_SCOPE                               7
RSVP_CLASS_IPV4_SCOPE	                       1			
RSVP_CLASS_IPV6_SCOPE                          2							
RSVP_CLASS_STYLE	                             8
RSVP_CLASS_STYLE_CTYPE_IPv4                    1
RSVP_CLASS_STYLE_CTYPE_IPv6                    2

RSVP_CLASS_FLOW_SPEC                            9
RSVP_CLASS_FLOW_SPEC_CTYPE_RESV                 1
RSVP_CLASS_FLOW_SPEC_CTYPE_INV_SERV		     2

RSVP_CLASS_FILTER_SPEC                         10
RSVP_CLASS_FILTER_SPEC_CTYPE_IPV4              1
RSVP_CLASS_FILTER_SPEC_CTYPE_IPV6              2
RSVP_CLASS_FILTER_SPEC_CTYPE_FLOW_LABEL        3
/* RFC 3209 RSVP-TE Extensions */
RSVP_CLASS_FILTER_SPEC_CTYPE_LSP_TUNNEL_IPV4   7
RSVP_CLASS_FILTER_SPEC_CTYPE_LSP_TUNNEL_IPV6   8

RSVP_CLASS_SENDER_TEMPLATE                     11
RSVP_CLASS_SENDER_TEMPLATE_IPV4                1
RSVP_CLASS_SENDER_TEMPLATE_IPV6                2
RSVP_CLASS_SENDER_TEMPLATE_IPV6_FLOW_LABEL     3
/* RFC 3209 RSVP-TE Extensions */
RSVP_CLASS_SENDER_TEMPLATE_LSP_TUNNEL_IPV4     7
RSVP_CLASS_SENDER_TEMPLATE_LSP_TUNNEL_IPV6     8

RSVP_CLASS_SENDER_TSPEC                        12
RSVP_CLASS_SENDER_TSPEC_CTYPE_INTSERV          2

RSVP_CLASS_ADSPEC                              13
RSVP_CLASS_ADSPEC_INTSERV                      2
   
RSVP_CLASS_POLICY_DATA                         14
RSVP_CLASS_POLICY_DATA_CTYPE_GENERIC           1

RSVP_CLASS_RESV_CONFIRM                        15
RSVP_CLASS_RESV_CONFIRM_CTYPE_IPV4             1
RSVP_CLASS_RESV_CONFIRM_CTYPE_IPV6             2

/* RFC 3206 RSVP-TE Objects */

RSVP_CLASS_LABEL                               16
RSVP_CLASS_LABEL_CTYPE_GENERIC                 1

RSVP_CLASS_LRO                                 19
RSVP_CLASS_LRO_CTYPE_GENERIC                   1
RSVP_CLASS_LRO_CTYPE_ATM                       2
RSVP_CLASS_LRO_CTYPE_FR                        3

RSVP_CLASS_ERO                                 20
RSVP_CLASS_ERO_CTYPE_GENERIC                   1
RSVP_CLASS_ERO_CTYPE_GENERIC_SUBOBJ_IPV4       1
RSVP_CLASS_ERO_CTYPE_GENERIC_SUBOBJ_IPV6       2
RSVP_CLASS_ERO_CTYPE_GENERIC_SUBOBJ_AS         3

RSVP_CLASS_RRO                                 21
RSVP_CLASS_RRO_CTYPE_GENERIC                   1


/* RFC 3209 RSVP-TE Extensions */
RSVP_CLASS_HELLO                               22
RSVP_CLASS_HELLO_CTYPE_REQUEST                 1
RSVP_CLASS_HELLO_CTYPE_ACK                     2

RSVP_CLASS_SESSION_ATTRIBUTE                     207
RSVP_CLASS_SESSION_ATTRIBUTE_CTYPE_LSP_TUNNEL_RA 1
RSVP_CLASS_SESSION_ATTRIBUTE_CTYPE_LSP_TUNNEL    7


typedef enum
{
   RSVP_CLASS_NULL,
   RSVP_CLASS_SESSION, 
   RSVP_CLASS_RSVP_HOP,
   RSVP_CLASS_INTEGRITY,
   RSVP_CLASS_TIME_VALUES,
   RSVP_CLASS_ERROR_SPEC,
   RSVP_CLASS_SCOPE,   
   RSVP_CLASS_STYLE,
   ......

}rsvp_class_type_t;

struct rsvp_obj_hdr
{
   u_int16_t length;
   rsvp_class_type_t class;
   u_char    c_type;
}

struct rsvp_obj_ero_sub_hdr
{



};

struct rsvp_obj_rro_sub_hdr
{


}








rsvp_obj.c

/*---------------------------------------------
 * Decodes the object header in stream->putp
 * and fills up struct rsvp_obj_hdr 
 *--------------------------------------------*/
void
rsvp_obj_decode_obj_hdr (struct stream *s,
                         struct rsvp_obj_hdr);

void
rsvp_obj_insert_obj_hdr (struct stream *s,
                         u_int16_t length,
                         u_char class_num,
                         u_char c_type);

/*-------------------------------------------
 * This API calculates and inserts the length
 * field of the object into obj_hdr. obj_startp
 * is pointer to the start of the object.
 *------------------------------------------*/
void
rsvp_obj_insert_obj_length (struct stream *s,
                            int obj_startp);
/*--------------------------------------------
 * Object Builders. These all intern calls
 * rsvp_obj_insert_obj_hdr 
 *-------------------------------------------*/
void
rsvp_obj_insert_label (struct stream *s, 
                       u_int32_t label);
void
rsvp_obj_insert_label_request (struct stream *s, 
                               int l3pid);
void
rsvp_obj_insert_atm_label_request (struct stream *s, 
                                   int l3pid, 
                                   int flag_merge_capable,
                                   u_int16_t min_vpi, 
                                   u_int16_t min_vci, 
                                   u_int16_t max_vpi, 
                                   u_int16_t max_vci);
void
rsvp_obj_insert_fr_label_request (struct stream *s, 
                                  u_int16_t l3pid, 
                                  int dli_, 
                                  min_dlci, 
                                  max_dlci);



6. RSVP Softstate Module (rsvp_state.h/c)
=========================================
This module will handle the PSB (Path State Blocks) and RSB(Reservation State Blocks) and will generate events for RSVP LSP module . The rsvp_lsp module sits
one layer above the rsvp_state module.  This module has no clue about rsvp_lsp 
data structures as this module sits below the rsvp_lsp module. The rsvp_state
module provides interface for callbacks registration to notofy various events
w.r.t the states. The rsvp_lsp module registers callbacks with this module and
thsi module notifies the rsvp_lsp module through the callbacks registered with 
it. This module sits one layer above the rsvp_packet layer. The packet layer
job is limited to decoding/encoding path and resv messages as per the protocol
specification and interact with rsvp_network layer to send and receive
packets. The common language between rsvp_pacekts and rsvp_state module are the
various  infos defines in rsvp_state. The rsvp_state module requests the
rsvp_packet layer through the same infos.
 
rsvp_state.h
=================

/* The various info to be kept in PSB/RSB */

enum
{
   SESSION_INFO_LSP_TUNNEL_IPV4 = 1,
   SESSION_INFO_LSP_TUNNEL_IPV6 = 2
} rsvp_session_info_type_t;

struct rsvp_lsp_tunnel_ipv4_info
{
   struct in_addr end_point_addr;
   u_int16_t tunnel_id;
   struct u_int32_t ext_tunnel_id;
};

struct rsvp_lsp_tunnel_ipv6_info
{
   struct in6_addr end_point_addr;
   u_int32_t tunnel_id;
   u_int32_t ext_tunnel_id[4];
};

struct rsvp_session_info 
{
   int type;
   union
   {
      struct rsvp_lsp_tunnel_ipv4_info ipv4_lsp_info;
      struct rsvp_lsp_tunnel_ipv6_info ipv6_lsp_info;
   }u;
#define ipv4_lsp_info u.ipv4_lsp_info
#define ipv6_lsp_info u.ipv6_lsp_info
};

typedef enum
{
   LRO_INFO_TYPE_GEN	= 1,
   LRO_INFO_TYPE_FR	= 2,
   LRO_INFO_TYPE_ATM	= 3
} lro_info_type_t;

struct rsvp_lro_info_atm
{
   u_char m;
   u_int16_t min_vpi;
   u_int16_t min_vci;
   u_int16_t max_vpi;
   u_int16_t max_vci;    
};

struct rsvp_lro_info_fr
{
   int dlci_min;
   int dlci_max;
};

struct rsvp_lro_info
{
   int valid;
   int l3pid;
   int type;
   union 
   {
      struct rsvp_lro_info_atm info_atm;
      struct rsvp_lro_info_fr  info_fr; 
   }u;
#define info_atm u.info_atm
#define info_fr u.info_fr  
};

....

/* The PSB and RSB descriptor. The state values are only for MPLS LSP 
   TE Tunnels. These PSB/RSBs are sufficient only for maintaining LSP 
   Tunnels */

struct rsvp_psb
{
 /* Upstream Interface. For ingress LSP this would 
    be 0 */
   int if_index_phop;
   struct in_addr in_addr_phop;
 /* Backpointer to the downstream Interface. For Egress LSP this is 
    0 */  
   int if_index_nhop;
   struct in_addr in_addr_nhop;

 /* Parameters at PSB required to maintain mpls lsps */
   void integrity_info;
   struct rsvp_session_info session_info;
   void time_values_info;
   void ero_info;
   struct rsvp_lro_info lro_info;
   void session_attribute_info;
   void policy_data_info;
   /* Sender descriptors */
   void sender_template_info;
   void sender_tspec_info;
   void adspec_info;
   void rro_info;

 /* Timer that is fired when this psb times out. When hello or refresh 
    is received on this PSB then we need to reset this timer. This 
    timer is active only if this PSB is installed in Transit LSR  */  
   struct thread *t_psb_expire_timer;
 
 /* Timer when fired initiates a PSB refresh message. This timer is 
    active only when this PSB is installed at ingress LSR */ 
   struct thread *t_psb_refresh_timer;

 /* Pointer to its RSB */
   struct rsvp_rsb *rsb;
}


struct rsvp_rsb
{
/* The PSB Pointer */
   struct rsvp_psb *psb;

/* Parameters at RSB required to maintain mpls lsps */
   void integrity_info;
   void session_info;
   void rsvp_hop_info;
   void time_values_info;
   void resv_confirm_info;
   void scope_info;
   void policy_data_info;
   void style_info;
   void flow_desc_list_info;
   void filter_spec_list_info;
   u_int32_t label_info;
   void rro_info; 

 /* Timer that is fired when this rsb times out. When hello or refresh
    is received on this RSB then we need to reset this timer. This 
    timer is active only if this RSB is in Transit LSR */  
   struct thread *t_rsb_expire_timer;
 /* Timer is fired after every RSB refresh Interval. This timer is 
    active only if this RSB is installed in egress LSR */ 
   struct thread *t_rsb_refresh_timer;
}

PSB/RSB Data Structure Organization:
   
The keys for searching a PSB/RSB is Tunnel ID+ LSP ID  per source  - a psb is 
installed with SENDER_TEMPLATE and SESSION objects).

So first the PSBs are organized in groups for s source in_addr (32bit). 
Although ideally 2^32 sources are possible (keys), in practice assumed in a 
core transit LSR there could be MAX 1000 senders. So we will keep senders in 
hash of size 1000 (10 bits hash mask) to have almost a "perfect hashing".
I use Bob Jenkins jhash which is the most efficient hash to generate 32
bit keys from any arbitrary length of keys. Each hashed list per hash bucket
is an "ordered" list with sender_addr as key.

A per source specific PSB group will always have PSBs with a Unique Tunnel ID 
as Tunnel ID is specific to a source. PSB Groups are organized in a AVL tree.
Assuming there could be 10000 (~ 2^13) Tunnels per source, so worst case search 
in a AVL tree will take 13 node touches in AVL tree. Each node of AVL tree
will have PSBs with same session but diff sender template (lsp-id).So 
each AVL node will have an "ordered" linked list with ldp_id as key. Assuming 
that during MBB we can have 2 LSP-Ids so most of time the linked list will
have 2 PSBs.

So assuming that there could be in a transit LSR there could be 1000 sources,
and 10000 tunnels per source, the worst case search will take lookup in 
16 nodes. I guess for my phase 1 this would be OK :-).

The same applies to rsvp_rsbs. Here the keys vare taken from SESSION object
and FILTER_SPEC.

Data structures used for PSB/RSB:

#define RSVP_SENDER_HASH_SIZE	(1 << 10)

struct rsvp_sender_hash_entry
{
   struct in_addr sender_addr;
   struct avl_table *session_avl;
};

struct list *rsvp_sender_hash[SENDER_KEY_HASH_SIZE];

The hash-list contains entry of type struct rsvp_sender_hash_entry. The
list is an ordered tree with sender_addr as key.


Each node in avl_tree contains a list of rsvp_psb/rsbs that share the same 
session but different sender template.
 

Maintenance of Softstates/Timers:
=================================
Now we have done away with some basic organization of PSB/RSBs.

RSB/PSB Cleanup timers:
=======================
To deal with scalability we maintain only one garbage collection timer for
cleaning up rsvp_psbs/rsvp_rsbs that times out.

The cleanup timer of every PSB/RSB is decided by timevalues that it receives
from its PHOP. We make the timer fire eveny 5 seconds. (min cleanup time is
5 seconds). Evertime it fires, the handler parses each PSB/RSB and checks
if it exceeds its timeout interval. If yes, then it deletes the PSB/RSB
and sends the corresponding path/resv error messages.

As the timer needs to parse every PSB/RSB so for simplicity we add each
psb/rsb into a cleanup list. Only transit/egress PSBs are in the list as 
we don't need to claenup the ingress PSB/RSBs, Similiary only igress/transit
LSRs RSBs needs cleanup.
 
rsvp->psb_cleanup_list
rsvp->rsvp_cleanup_list

RSB/PSB Refresh Timers
======================
The refresh timers are configured per RSVP interface. So we keep one
timer per interface that refreshes all PSB/RSBs on that interface.
This periodic timer at the node scans the RSB/PSBs to create new path/resv
messages towards the originator of that message.

rsvp_if->refresh_timer.
So we need to also maintain the refresh_list per interface. This lists 
contain psb/rsbs for which it is the nexthop interface.

rsvp->if->psb_refresh_list.
rsvp->if->rsb_refresh_list.

Whenever the timer fires, it parses through the lists and generates
refresh message for each psb/rsb in the list.              
 
Callbacks Stuff
===============


rsvp_softstate.c
================

APIs provided.
=============
1. struct rsvp_sender_hash_entry *rsvp_sender_hash_entry_create (void)
   
   It creates a rsvp_sender_hash_entry and returns the pointer.
 
2. int rsvp_sender_hash_bucket (struct in_addr *sender_addr)
   It returns a hash bucket for the input key as sender_addr;
   
3. int rsvp_sender_hash_bucket_lookup_sender_key (struct in_addr *sender_addr,
                                                  int hash,
                                                  struct rsvp_sender_hash_entry 
                                                  *entry,
                                                  u_char create_flag);

   3.1 It parses the list in the hash bucket of input arg "hash" 
       with sender_addr as key. If the entry is found then its pointer is 
       filled into input arg "entry" and returns 1. If not found and
       create_flag is not set then return 0. 
   3.2 If entry not found and create_flag is set to one then create a new one 
       with rsvp_sender_hash_entry_create (). Fill the addr key in the entry
       and initialize the session_avl. Fill the entry pointer in input arg 
       "entry' and return 2.

4. struct list* rsvp_session_avl_lookup_tunid_key (struct avl_table*session_avl,
                                                   u_int16_t *tunnel_id)
   This API looks up a Session AVL Tree with tunnel_id as key and returns 
   pointer to the rsvp_rsb/rsvp_psb list in the avl_node that matches the 
   key. If not found is returns NULL.

5. struct list* rsvp_session_avl_create_tunid_key (struct avl_table 
                                                   *session_avl,
                                                   u_int16_t *tunnel_id)
   This API creates a avl_node with list of rsb/psbs as data and returns the 
   list of rsvp_psb/rsvp_rsbs beraing the same session_id but diff lsp_id.

6. void rsvp_session_avl_delete_tunid_key (struct avl_table *session_avl,
                                           u_int16_t *tunnel_id);
   This API deletes all rsvp_psb/rsvp_rsbs that matches the same tunnel_id
   but may have diff lsp_id.

7. void * rsvp_state_list_lookup_lspid_key (struct list *lspid_list,
                                            u_int16_t lsp_id)

   Returns pointer to the struct rsvp_psb or struct rsvp_rsb that matches
   the lsp_id.
  
8. static struct rsvp_psb *rsvp_state_psb_create (void)
   
   Creates an object of type struct rsvp_psb in heap and returns it.

9. static void rsvp_state_psb_free (struct rsvp_psb *)

   Frees an object of type struct rsvp_psb from heap.

10. static struct rsvp_rsb *rsvp_state_rsb_create (void)

   Creates an object of type struct rsvp_rsb in heap and returns it.

11. static void rsvp_state_rsb_free (struct rsvp_rsb *)

   Frees an object of type struct rsvp_rsb from heap and returns it. 

12. int rsvp_state_psb_lookup_create (struct in_addr *sender_addr,
                                      struct u_int16_t *tunnel_id,
                                      struct u_int16_t *lsp_id,
                                      struct in_addr *dst_addr,
                                      struct rsvp_psb *psb);
   
   This API looks up a PSB with the input keys, if found an existing rsvp_psb
   then it fills its pointer to input arg psb and returns 1. If not found then 
   it creates one and fills its pointer to input arg psb and returns 0. If
   creation fails then return -1.

   This API is invoked in a Transit/Egress LSR for the LSP (or PSB) when a 
   path message is  received. This API is used in a ingress LSR when a new
   psb needs to be created.

   The API does the following:

   The arguments required are sender_addr, tunnel_id, dest_addr, lsp_id and
   struct rsvp_psb

   12.1 Get the hash bucket for the sender_addr as key.
       hash = rsvp_sender_hash_key (struct in_addr *sender_addr)      
 
   12.2 Lookup the hash list with the sender_addr.

   int rsvp_sender_hash_bucket_lookup_sender_key 
   (struct in_addr *sender_addr,
    int hash,
    struct rsvp_state_sender_hash_entry entry *);
   if returns 0 then return from this API. If 1 then proceed to 5.3. If
   returns 2 then proceed to 5.4. 

   12.3. Do avl_find with the key as tunnel_id. If found go to 5.6.
        If not found and create_flag is not set then return from the API
        with 0. If create_flag is set then proceed.
   12.4  Insert an entry avl_node with avl_insert (tunnel_id) .
   12.5  Create a psb. rsvp_state psb_create (). Fill with relevant parameters.
        add to the list in avl_node. 
   12.6  Returns the rsvp_psb.
   
 
13. void rsvp_state_psb_delete (struct rsvp_psb *);
   This unhooks it from the hash/avl_tree. Then is unhooked from the 
   the rsvp_if->refresh_list. Here the rsvp_if is the outgoing  interface
   for next hop. The free it from heap.

   This API is used when a 
   2.1. A Path Tear message is received
   2.2  The rsvp->clean_up_timer finds the a psb is aged out.
   2.3  A Path Err Message is received.

14. struct rsvp_rsb *rsvp_state_rsb_create (struct in_addr *sender_addr,
                                           u_int16_t *tunnel_id,
                                           u_int16_t *lsp_id,
                                           struct in_addr *dst_addr)
   This is used to create a new RSB when a Resv Message is received.
   When a Resv message is received first it looks up the matching PSB by
   using rsvp_state_psb_lookup with the relevant keys. If not found then 
   it is created.

   This allocates a struct rsvp_rsb and hooks into sender hash/session
   avl_tree. Further if this is transit or egress node then add to 
   rsvp_if->rsb_refresh_list where struct rsvp_if is the outgoing if for 
   the rsbp_rsb. Also add to rsv->rsb_cleanup_list if this node is ingress
   or transit for the LSP.

15. void rsvp_state_rsb_delete (struct rsvp_rsb *)
   
   This API unhooks the rsvp_rsb from the sender hash/avl_tree and futher
   unhooks from the rsvp_if->rsb_refresh_list and rsvp->rsb_cleanup_list.
   Then it frees the object from heap.

   This API is called when Path Tear/ Resv Tear/Resv Err message is received. 
   Further this is called when the rsvp->rsb_cleanup_timer finds that the 
   struct rsvp_rsb is timed out.

16. struct rsvp_rsb *rsvp_state_rsb_lookup (struct in_addr *sender_addr,
                                          u_int32_t *tunnel_id,
                                          u_int32_t *lsp_id,
                                          struct in_addr *dst_addr)
   This API looks  up the struct rsvp_rsb that matches the inpt keys.
   This API is called to lookup when a Resv Err/Resv Tear Message is received.
 
17. void rsvp_state_psb_refresh (struct rsvp_psb *);

   This is called when rsvp_if->refresh_timer expires and it parses 
   through the rsvp_if->psb_refresh_list.

18. void rsvp_state_rsb_refresh (struct rsvp_rsb *);
   
   This is called when rsvp_if->refresh_timer expires and it parses
   through rsvp_if->rsb_refresh_list.

19. void rsvp_state_psb_cleanup (struct rsvp_psb *)
   
   This is called from rsvp->cleanup_timer handler if a struct rsvp_psb
   is timed out.
   The API does the following.

            rsvp_state_psb_cleanup (struct rsvp_psb *)
                             |
                             v
            rsvp_packet_path_tear_send (...) in rsvp_packet.c
                             |
                             v
            rsvp_state_psb_delete (struct rsvp_psb *)
                             |
                             v
            rsvp_state_rsb_delete (struct rsvp_rsb *) 
            where rsvp_rsb = rsvp_psb->rsb. 

20. void rsvp_state_rsb_cleanup (struct rsvp_rsb *)
 
    This is called when rsvp_cleanup_timer handler if a struct rsvp_rsb
    is timed out.
    The API does the following:
     
           rsvp_state_rsb_cleanup (struct rsvp_rsb *)
                             |
                             v
           rsvp_packet_resv_tear_send (..) in rsvp_packet.c
                             |
                             v
           rsvp_state_rsb_delete (struct rsvp_rsb *);


                    


   



Callbacks library for softstates

static struct rsvp_softstate_callback_info 
rsvp_softstate_cb_info [RSVP_SOFTSTATE_EVENTS_MAX][RSVP_SOFTSTATE_CLIENTS_MAX]

rsvp_softstate_register_callback (int event, 
                                  int (*fn)(void));
rsvp_softstate_deregister_callback (int event, 
                                    int (*fn)(void));
rsvp_softstate_notification_callback (int event, 
                                      struct rsvp_softstate_cb_info*); 

Callbacks Events

RSVP_SOFTSTATE_EVENT_PSB_ADD /* New PSB Added */
RSVP_SOFTSTATE_EVENT_PSB_DEL /* Existing RSB Deleted */
RSVP_SOFTSTATE_EVENT_PSB_UPD /* Existing PSB Updated */
RSVP_SOFTSTATE_EVENT_RSB_ADD /* New RSB Added */
RSVP_SOFTSTATE_EVENT_RSB_DEL /* Existing RSB Deleted */
RSVP_SOFTSTATE_EVENT_RSB_UPD /* Existing RSB Updated */


/* Interface Specfific Hash. Add the PSBs in a hash list 
   per if_index. This is needed to handle interface specific events 
   The hash key is if_index and data is struct rsvp_psb/rsvp_rsb
   The interface specific hash objects will be hooked to struct rsvp*/




RSVP Zebra Module
=================
This module interacts with the zMPLS daemon.

1) Gets all interface specific info and traps all interface events.
2) Gets IP addresses on the interfaces and all add/del ip addr events
3) Gets Routing Info.

rsvp_zebra.h



rsvp_zebra.c



RSVP Refresh Reduction Extensions RFC 2961
===========================================
This extension categorizes RSVP messages into two types: trigger and
refresh messages.Trigger messages are those RSVP messages that advertise state or any other information not previously transmitted. 

New Message
RSVP_MSG_BUNDLE
Rules:
1) Sent with IP address of the sending router to the neigbor.
2) Shouldn't be sent with Router Alert Option as its destined to next 
   neighbor.

/* RFC 2961 says no max size limit as IP will fragment, but in this implementation we limit it to 1500 bytes to respect standard MTU */
#define RSVP_BUNDLE_MSG_MAX_LEN 		1500 
#define RSVP_BUNDLE_TRIGGER_MSG_INTERVAL	
#define RSVP_BUNDLE_REFRESH_MSG_INTERVAL


Bundle Header


RSVP Bundle Message Processing
==============================
rsvp_msg_bundle_rcv (struct rsvp_if)
        |
        |
        v
if (rsvp_if->cflags & RSVP_CFLAG_RR)----no-->discard
        |yes
        |
        v
if (Send_TTL in bundle header == IP TTL in IP Header)--
        |                                           |
        |yes                                       No 
        |                                           |
        v                                Do nothing
Set(rsvp_peer(phop)->cflags & RSVP_PEER_CFLAGS)
        |
        |
        v
if(bundle_hdr->version == 1) && (rsvp_msg_bundle_checksum_error())
        |                                 |
        yes                              NO
        |                                 |
        |                               discard
rsvp_msg_bundle_decap(..)
Decapsulate bundle and process individual messages  
        |
        |
   call handler based on each message type


MSG_ID Extension
================
New objects

MESSAGE_ID
MESSAGE_ID_ACK
MESSAGE_ID_NACK