Linux network protocol stack Analysis Note 13-Route 3-fiber 2

Source: Internet
Author: User
Of course, we choose the legacy interfaces in Chapter 1 to go to the analysis.

Fiber _ Lookup () We mentioned earlier that during fib initialization, The config_ip_multiple_tables macro leads to two methods of Fib table initialization, so there is a situation where multiple route tables exist and no more route tables exist, let's first look at the absence of Multiple Route tables. Static inline int maid (struct net * Net, const struct flowi * handle,
Struct maid * res)
{
Struct fib_table * table;

Table = maid (net, rt_table_local); first check local
If (! Table-> tb_lookup (table, tables, Res ))
Return 0;

Table = maid (net, rt_table_main); then check main
If (! Table-> tb_lookup (table, tables, Res ))
Return 0;
Return-enetunreach;
} Static inline struct maid (struct net * Net, u32 ID)
{
Struct hlist_head * PTR;

PTR = id = rt_table_local?
& Net-> ipv4.fib _ table_hash [table_local_index]:
& Net-> ipv4.fib _ table_hash [table_main_index];
Return hlist_entry (PTR-> first, struct fib_table, tb_hlist); find fib_table based on the input ID
} A figure in the previous chapter illustrates this structure.

! Table-> tb_lookup (table, sums, Res) is fn_hash_lookupstatic int
Fn_hash_lookup (struct fib_table * TB, const struct flowi * fail, struct fib_result * res)
{
Int err;
Struct fn_zone * FZ;
Struct fn_hash * t = (struct fn_hash *) TB-> tb_data; get the queue in the routing area

Read_lock (& fib_hash_lock );
For (FZ = T-> fn_zone_list; FZ = FZ-> fz_next) {scan the network zone
Struct hlist_head * head;
Struct hlist_node * node;
Struct fib_node * F;
_ Be32 K = fz_key (region-> fl4_dst, Fz); obtain the network number fl4_det (Fz)-> fz_mask) of the target address in the network zone)

Head = & FZ-> fz_hash [fn_hash (K, Fz)]; fn_hash (K, Fz) Get the hash keyword get the hash chain Header
Hlist_for_each_entry (F, node, Head, fn_hash ){
If (F-> fn_key! = K) Use fn_key to find the matched fib Node
Continue;

Err = maid (& F-> fn_alias, go to fib semantic search
Records, res,
FZ-> fz_order );
If (ERR <= 0)
Goto out;
}
}
Err = 1;
Out:
Read_unlock (& fib_hash_lock );
Return err;
}

Int maid (struct list_head * head, const struct flowi * handle,
Struct fib_result * res, int prefixlen) Here head is F-> fn_alias Structure
{
Struct maid * Fa;
Int nh_sel = 0;

List_for_each_entry_rcu (FA, Head, fa_list ){
Int err;

If (Fa-> fa_tos &&
Fa-> fa_tos! = Comparison-> fl4_tos) Comparison TOS
Continue;

If (Fa-> fa_scope <strong-> fl4_scope) compares the routing range scope
Continue;

Fa-> fa_state | = fa_s_accessed;

Err = maid [fa-> fa_type]. error; get the forwarding type error code for specific processing based on the error code
If (ERR = 0) {allowed forwarding type
Struct maid * fi = fa-> fa_info;

If (FI-> maid & rtnh_f_dead) if the forwarding node fails
Continue;

Switch (Fa-> fa_type ){
Case rtn_unicast: single object forwarding
Case rtn_local: Local forwarding
Case rtn_broadcast: Broadcast forwarding
Case rtn_anycast: Any forwarding
Case rtn_multicast: multi-object forwarding
For_nexthops (FI) {for each forwarding address in the forwarding information, use each fiber-NH structure.
If (NH-> nh_flags & rtnh_f_dead)
Continue;
If (! Response-> OIF | response-> OIF = NH-> nh_oif)
Break;
}
# Ifdef config_ip_route_multipath
If (nhsel <fi-> fig ){
Nh_sel = nhsel;
Goto out_fill_res;
}
# Else
If (nhsel <1) {non-multi-path route forwarding address number must be less than 1
Goto out_fill_res; jump
}
# Endif
Endfor_nexthops (FI );
Continue;

Default:
Printk (kern_warning "Maid bad type % # x \ n ",
Fa-> fa_type );
Return-einval;
}
}
Return err;
}
Return 1;

Out_fill_res:
Res-> prefixlen = prefixlen; enter the query result. Here, the route information is found in fib.
Res-> nh_sel = nh_sel;
Res-> type = fa-> fa_type;
Res-> scope = fa-> fa_scope;
Res-> Fi = fa-> fa_info;
Atomic_inc (& res-> fi-> fig );
Return 0; return successful
} According to the above process, I tracked the data structure variable Query Process and sorted out the following figure. Of course, the specific role of each member in each structure is not analyzed in detail here, this is a detailed and slow research. Here we will only sort out the process.

Let's take a look at how to enable multiple route tables-> int fiber _ Lookup (struct net * Net, struct flowi * fail, struct fiber _result * res)

{
Struct maid Arg = {
. Result = res,
};
Int err;

Err = maid (net-> ipv4.rules _ ops, sums, 0, & Arg );
Provides rules_ops for searching fib rule
Res-> r = Arg. Rule;

Return err;
}

Int maid (struct maid ops * ops, struct flowi * FL,
Int flags, struct maid * Arg)
{
Struct maid * rule;
Int err;

Rcu_read_lock ();

List_for_each_entry_rcu (rule, & OPS-> rules_list, list ){
Jumped:
If (! Fib_rule_match (rule, OPS, FL, flags)
Continue;

If (Rule-> action = fr_act_goto) {check whether the action flag is forwarded to another rule
Struct maid * target;

Target = rcu_dereference (Rule-> ctarget );
If (target = NULL ){
Continue;
} Else {
Rule = target;
Goto jumped;
}
} If (Rule-> action = fr_act_nop) No action is specified for the else if (Rule-> action = fr_act_nop ),
Continue;
Else
Err = OPS-> action (rule, FL, flags, ARG); executes the action of rule.

If (Err! =-Eagain ){
Fib_rule_get (rule );
Arg-> rule = rule;
Goto out;
}
}

Err =-esrch;
Out:
Rcu_read_unlock ();

Return err;
} This function involves another structure in the previous chapter.

Static int maid (struct maid * Rule, struct maid * ops,
Struct flowi * FL, int flags)
{
Int ret = 0;

If (Rule-> ifindex & (Rule-> ifindex! = FL-> IIF) detect the device ID
Goto out;

If (Rule-> MARK ^ FL-> MARK) & rule-> mark_mask) mask match
Goto out;

Ret = OPS-> match (rule, FL, flags );
Out:
Return (rule-> flags & fib_rule_invert )? ! RET: ret;
}

Static struct maid = {
. Family = af_inet, protocol stack
. 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,
}; Fib4_rule_match ()

Static int maid (struct maid * Rule, struct flowi * FL, int flags)
{
Struct maid * r = (struct maid *) rule;
_ Be32 daddr = fL-> fl4_dst;
_ Be32 saddr = fL-> fl4_src;

If (saddr ^ r-> SRC) & R-> srcmask) | compare the source address destination address with the routing rule
(Daddr ^ r-> DST) & R-> dstmask ))
Return 0;

If (R-> TOS & (R-> tos! = FL-> fl4_tos) TOS match
Return 0;

Return 1;
}

Static int maid (struct maid * Rule, struct flowi * handle,
Int flags, struct maid * Arg)
{
Int err =-eagain;
Struct fib_table * TBL;

Switch (rule-> action) {check the action ID
Case fr_act_to_tbl:
Break;

Case fr_act_unreachable:
Err =-enetunreach;
Goto errout;

Case fr_act_prohibit:
Err =-eacces;
Goto errout;

Case fr_act_blackhole:
Default:
Err =-einval;
Goto errout;
}

If (TBL = maid (Rule-> fr_net, rule-> table) = NULL) Find the route table function
Goto errout;

Err = TBL-> tb_lookup (TBL, marker, (struct fib_result *) Arg-> result); Use the route table function to query logs.
If (ERR> 0)
Err =-eagain;
Errout:
Return err;
}

Struct maid * maid (struct net * Net, u32 ID)
{
Struct fib_table * TB;
Struct hlist_node * node;
Struct hlist_head * head;
Unsigned int h;

If (ID = 0)
Id = rt_table_main;
H = ID & (maid-1 );

Rcu_read_lock ();
Head = & net-> ipv4.fib _ table_hash [H]; here, the hash table is the hash table of the size of 256, where the table is created through fib_new_table
Hlist_for_each_entry_rcu (TB, node, Head, tb_hlist ){
If (Tb-> tb_id = ID ){
Rcu_read_unlock ();
Return TB;
}
}
Rcu_read_unlock ();
Return NULL;
} TBL-> tb_lookup: This is the Registered TB lookup function. This is the same as the case where multiple route tables are not enabled in this article.

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.