/*
 * $Id: view.h,v 1.1.1.1 1998/08/10 20:06:52 dogcow Exp $
 * originally Id: view.h,v 1.9 1998/07/17 18:23:24 masaki Exp 
 */

#ifndef _VIEW_H
#define _VIEW_H

#include <stack.h>
#include <trace.h>
#include <hash.h>
#include <radix.h>
#ifndef HAVE_PTHREAD_H
#include <pthread_fake.h>
#else
#include <pthread.h>
#endif /* HAVE_PTHREAD_H */

#define MAX_BGP_PEERS		32
#define MAX_BGP_VIEWS		32

#include <aspath.h>

struct _bgp_route_head_t;
typedef struct _bgp_route_t {
    struct _bgp_route_head_t *head;	/* pointer back to our route_head */
    int pref;			/* pref determined bu metric/policy */
    bgp_attr_t *attr;
    time_t time;
    u_char aggregated;
} bgp_route_t;


/* state bits */
#define VRTS_DELETE	 0x01	/* about to be deleted -- route is withdrawn */
#define VRTS_ACTIVE	 0x02
#define VRTS_CHANGE	 0x04
#define VRTS_SUPPRESS	 0x08
#define VRTS_SUMMARY	 0x10

/* the change bits explain what caused the change in state */
typedef struct _bgp_route_head_t {
    u_long state_bits;		/* active, holddown, withdrawn */
    /* u_long   change_bits;    new, change, withdrawn */
    u_long peer_mask;		/* mask of peers we sent this route to */
    prefix_t *prefix;
    bgp_route_t *active;	/* a pointer to best, or active route_node */
    bgp_route_t *last_active;	/* a pointer to last active route_node */
    LINKED_LIST *ll_routes;
    bgp_route_t *imported;	/* a pointer to imported route */
    radix_node_t *radix_node;
} bgp_route_head_t;


#define BGP_AGGOPT_AS_SET 0x01
#define BGP_AGGOPT_SUMMARY_ONLY 0x02

typedef struct _aggregate_t {
    prefix_t *prefix;
    bgp_attr_t *attr;
    u_long option;
    radix_node_t *radix_node;
    bgp_route_t *route;
} aggregate_t;


typedef struct _view_t {
    pthread_mutex_t mutex_lock;
    int num_active_routes;
    u_long peer_mask;		/* mask of peers route annouced to */
    int family;
    radix_tree_t *radix_tree;
    trace_t *trace;
    LINKED_LIST *ll_ann_routes;	/* changed routed heads */
    LINKED_LIST *ll_with_routes;	/* deleted routed heads */
    /* void *user;               hook for program or user specific data */
    /* HASH_TABLE               peer_hash[MAX_BGP_PEERS]; */

    radix_tree_t *agg_tree;
    int rib;			/* 1 == need to update the rib */
    int viewno;
} view_t;

#define VIEW_RADIX_WALK(Xview, Xroute_head) \
	do { \
	    radix_node_t *Xnode; \
	    RADIX_WALK (Xview->radix_tree->head, Xnode) { \
		Xroute_head = RADIX_DATA_GET (Xnode, bgp_route_head_t);

#define VIEW_RADIX_WALK_END \
	    } RADIX_WALK_END; \
	} while (0)


typedef struct _update_bucket_t {
    LINKED_LIST *ll_prefix;
    bgp_attr_t *attr;
    prefix_t *nexthop;
} update_bucket_t;


/* public functions */
view_t *New_View (u_int maxbitlen);
int view_close (view_t * view);
int view_open (view_t * view);

bgp_route_t *
  bgp_add_route (view_t * view, prefix_t * prefix, bgp_attr_t * attr,
		 u_int pref);
int bgp_del_route (view_t * view, prefix_t * prefix, bgp_attr_t * attr);
int bgp_update_route (prefix_t * prefix, generic_attr_t * new,
		      generic_attr_t * old, int pref);
bgp_route_t *view_find_bgp_active (view_t * view, prefix_t * prefix);
prefix_t *view_find_best_route (view_t * view, prefix_t * prefix);
int bgp_process_changes (view_t * view);
int process_bgp_update (bgp_peer_t * peer, u_char * cp, int length);

aggregate_t *
  view_add_aggregate (view_t * view,
		      prefix_t * prefix, u_long opt);
int view_del_aggregate (view_t * view, prefix_t * prefix);
void view_print_aggregate (int viewno, void (*fn) ());

void bgp_establish_peer (bgp_peer_t * peer);
void view_delete_peer (view_t * view, bgp_peer_t * peer);

int show_view (uii_connection_t * uii, int view);
int trace_bgp_view (uii_connection_t * uii, char *s);
int no_trace_bgp_view (uii_connection_t * uii, char *s);

#endif /* _VIEW_H */
