In the previous chapter, we saw that we searched for the route information through fib_lookup. In this chapter, we can see what fib is.
FIB (forward information base) forwarding information library
Inet_init ()-> ip_init ()-> ip_rt_init ()->
20174_dst_ops.kmem_cache=
Kmem_cache_create ("ip_dst_cache", sizeof (struct rtable), 0, rtable high-speed cache Creation
Slab_hwcache_align | slab_panic, null); rt_hash_table = (struct rt_hash_bucket *) create a hash table for routing Cache
Alloc_large_system_hash ("IP Route cache ",
Sizeof (struct rt_hash_bucket ),
Rhash_entries,
(Totalram_pages> = 128*1024 )?
15: 17,
0,
& Rt_hash_log,
& Rt_hash_mask,
Rhash_entries? 0: 512*1024 );
Memset (rt_hash_table, 0, (rt_hash_mask + 1) * sizeof (struct rt_hash_bucket); ip_fib_init ()-> Register rtnetlink messages related to routes and their processing functions, mainly deal with route addition and Deletion
Rtnl_register (pf_inet, rtm_newroute, inet_rtm_newroute, null );
Rtnl_register (pf_inet, rtm_delroute, inet_rtm_delroute, null); rtnl_register (pf_inet, rtm_getroute, null, inet_dump_fib );
Register_pernet_subsys (& fib_net_ops); register the protocol stack subsystem, that is, the routing system. Key Point: maid
Register_netdevice_notifier (& fib_netdev_notifier); notification link Registration
Register_inetaddr_notifier (& fib_inetaddr_notifier );
Fib_hash_init () Fib_hash_init () This function appears in both the fib_hash.c fib_trie.c files. The system can configure two route table organization algorithms. The default hash algorithm is void _ init fib_hash_init (void)
{
Fn_hash_kmem = kmem_cache_create ("ip_fib_hash", sizeof (struct fib_node), create 0 in the fib_node cache, and create 0 in the slab_panic, null );
Fn_alias_kmem = kmem_cache_create ("ip_fib_alias", sizeof (struct fib_alias), create 0 for the fib_alias cache, slab_panic, null );
}
Main data structure: struct fib_node {represents the subnet to which a route points
Struct hlist_node fn_hash; hash Node
Struct list_head fn_alias; route alias
_ Be32 fn_key; subnet address
Struct fib_alias fn_embedded_alias; embedded route alias
}; Struct maid {
Struct list_head fa_list;
Struct fib_info * fa_info; the routing information structure stores how data packets are processed
U8 fa_tos; ToS
U8 fa_type; route type
U8 fa_scope; route range
U8 fa_state; Status flag
# Ifdef config_ip_fib_trie
Struct rcu_head RCU;
# Endif
}; Maid: static struct pernet_operations maid = {
. Init = maid,
. Exit = maid,
}; Maid (net );
Nl_fib_lookup_init (net); Netlink Initialization
Fib_proc_init (net); initialize the proc file system}
Static int _ net_init ip_fib_net_init (struct net * Net)
{
Int err;
Unsigned int I;
Net-> IPv4.Fib_table_hash= Kzarloc (
Sizeof (struct hlist_head) * fib_table_hashsz, gfp_kernel); Apply for a 256 hash table
If (net-> ipv4.fib _ table_hash = NULL)
Return-enomem;
For (I = 0; I <maid; I ++)
Init_hlist_head (& net-> ipv4.fib _ table_hash [I]); initializes the conflict chain of each hash table
Err = fib4_rules_init (net); with 256 tables, you have to mention the Linux route table Search rules, that is, the policy Route IP address rule Add/del...
If (ERR <0)
Goto fail;
Return 0;
Fail:
Kfree (net-> ipv4.fib _ table_hash );
Return err;
}
Fib4_rules_init () has two. If you open a macro with Multiple Route tables, we can see int _ net_init fib4_rules_init (struct net * net) in Fig)
{
Int err;
Struct fib_rules_ops * OPS;
Allocate space to OPS and initialize ops with fib4_rules_ops_template
Ops = kmemdup (& fib4_rules_ops_template, sizeof (* OPS), gfp_kernel );
If (Ops = NULL)
Return-enomem;
Init_list_head (& OPS-> rules_list );
OPS-> fro_net = net;
Fib_rules_register (OPS); link different route table rules of the protocol family to the net rules_ops through the list string.
List_add_tail_rcu (& OPS-> list, & net-> rules_ops );
Err = maid (OPS );
If (ERR <0)
Goto fail;
Net-> ipv4.rules _ Ops = OPS;
Return 0;
Fail:
/* Also cleans all rules already added */
Fib_rules_unregister (OPS );
Kfree (OPS );
Return err;
} Static struct maid = {
. Family = af_inet, protocol family
. Rule_size = sizeof (struct fib4_rule ),
. Addr_size = sizeof (u32 ),
. Action = maid,
. Match = maid,
. Configure = maid,
. Compare = maid,
. Fill = maid,
. Default_pref = maid,
. Nlmsg_payload = maid payload,
. Flush_cache = maid cache,
. Nlgroup = rtnlgrp_rj4_rule,
. Policy = maid,
. Owner = this_module,
};
Fib_default_rules_init () create three basic route tables: local, main, and default. Rule table static int fib_default_rules_init (struct fib_rules_ops * OPS)
{
Int err;
Err = maid (Ops, 0, rt_table_local, FIG );
If (ERR <0)
Return err;
Err = maid (Ops, 0x7ffe, rt_table_main, 0 );
If (ERR <0)
Return err;
Err = maid (Ops, 0x7fff, rt_table_default, 0 );
If (ERR <0)
Return err;
Return 0;
}
Int maid (struct maid * ops, u32 pref, u32 table, u32 flags)
{
Struct maid * R;
R = kzarloc (OPS-> rule_size, gfp_kernel); apply for the FIB rule Structure
If (r = NULL)
Return-enomem;
Atomic_set (& R-> refcnt, 1 );
R-> action = fr_act_to_tbl;
R-> Pref = Pref;
R-> table = table;
R-> flags = flags;
R-> fr_net = hold_net (OPS-> fro_net );
/* The lock is not required here, the list in unreacheable
* At the moment this function is called */
List_add_tail (& R-> list, & OPS-> rules_list); add it to the rules_list of fib_rules_ops
Return 0;
}
Structure Definition of the main data structure routing rule function table
{
Int family; Protocol Stack
Struct list_head list; link to net-> rules_ops chain
Int rule_size; rule structure Length
Int addr_size; address Length
Int unresolved_rules;
Int nr_goto_rules;
INT (* Action) (struct fib_rule *, Action function pointer
Struct flowi *, Int,
Struct maid *);
INT (* match) (struct fib_rule *, matching function pointer
Struct flowi *, INT );
INT (* configure) (struct fib_rule *, configure the function pointer
Struct sk_buff *,
Struct maid *,
Struct nlattr **);
INT (* compare) (struct fib_rule *, comparison function pointer
Struct maid *,
Struct nlattr **);
INT (* fill) (struct fib_rule *, struct sk_buff *, fill in the function pointer
Struct fib_rule_hdr *);
U32 (* default_pref) (struct fib_rules_ops * OPS); find the priority function pointer
Size_t (* nlmsg_payload) (struct fib_rule *); function pointer for statistics of load data capabilities
/* Called after modifications to the rules set, must flush
* The route cache if one exists .*/
Void (* flush_cache) (struct fib_rules_ops * OPS); after modifying the rule queue, you must refresh the cached function pointer.
Int nlgroup;
Const struct nla_policy * policy;
Struct list_head rules_list; rule linked list for each route table
Struct module * owner;
Struct net * fro_net; relationship between net and OPS
}; Struct maid
{
Struct list_head list;
Atomic_t refcnt; reference count
Int ifindex; network device ID
Char ifname [ifnamsiz]; used to save the network device name
U32 mark; used for filtering
U32 mark_mask; mask
U32 Pref; Priority
U32 flags; flag bit
U32 table; route function table ID
U8 action; Action ID
U32 target;
Struct fib_rule * ctarget; current rule
Struct rcu_head RCU;
Struct net * fr_net; Net Structure pointer
}; Relationship between the above structures
If the config_ip_multiple_tables macro is not enabled, let's look at fib_frontend.cstatic int _ net_init fib4_rules_init (struct net * net)
{
Struct fib_table * local_table, * main_table;
Local_table = maid (rt_table_local); create a local routing function table
Return-enomem;
Main_table = maid (rt_table_main); create the main routing function table
If (main_table = NULL)
Goto fail;
Hlist_add_head_rcu (& local_table-> tb_hlist, inserted into the unified management queue
& Net-> ipv4.fib _ table_hash [table_local_index]); here is the 256 hash table applied for in ip_fib_net_init.
Hlist_add_head_rcu (& main_table-> tb_hlist,
& Net-> ipv4.fib _ table_hash [table_main_index]);
Return 0;
Fail:
Kfree (local_table );
Return-enomem;
}
Struct maid * maid (u32 ID)
{
Struct fib_table * TB;
TB = kmalloc (sizeof (struct fib_table) + sizeof (struct fn_hash), two new fib-related structures emerged here
Gfp_kernel );
If (TB = NULL)
Return NULL;
TB-> tb_id = ID;
TB-> tb_default =-1;
TB-> tb_lookup = fn_hash_lookup;
TB-> tb_insert = fn_hash_insert;
TB-> tb_delete = fn_hash_delete;
TB-> tb_flush = fn_hash_flush;
TB-> tb_select_default = fn_hash_select_default;
TB-> tb_dump = fn_hash_dump;
Memset (Tb-> tb_data, 0, sizeof (struct fn_hash ));
Return TB;
}
The main data structure, struct fib_table {fib_table, provides the route table with a method to query route information.
Struct hlist_node tb_hlist; hash Node
U32 tb_id; identifier
Int tb_default;
INT (* tb_lookup) (struct fib_table * TB, const struct flowi * Rows, struct fib_result * res); query
INT (* tb_insert) (struct fib_table *, struct fib_config *); insert
INT (* tb_delete) (struct fib_table *, struct fib_config *); Delete
INT (* tb_dump) (struct fib_table * Table, struct sk_buff * SKB, route forwarding
Struct netlink_callback * CB );
INT (* tb_flush) (struct fib_table * table );
Void (* tb_select_default) (struct fib_table * Table, select the default route
Const struct flowi * fail, struct fiber _result * res );
Unsigned char tb_data [0];
}; Struct fn_hash {queue structure definition in the routing area
Struct fn_zone * fn_zones [33]; route zone queue
Struct fn_zone * fn_zone_list; pointing to the first route area table
}; Struct fn_zone {routing area structure definition
Struct fn_zone * fz_next;/* Next not empty zone */points to the structure of the next non-empty routing Zone
Struct hlist_head * fz_hash;/* hash table pointer */HASH queue
Int fz_nent;/* number of entries */number of Route entries
Int fz_divisor;/* hash divisor */number of hash Headers
U32 fz_hashmask;/* (fz_divisor-1) */mask of the hash Header
# Define fz_hashmask (Fz)-> fz_hashmask)
Int fz_order;/* zone Order */subnet mask count
_ Be32 fz_mask; Subnet Mask
# Define fz_mask (Fz)-> fz_mask)
};
From the perspective of fib-related initialization, a considerable amount of data structures have emerged. We will look at how these structures are used from the perspective of processing operations, and what routing operations are achieved