1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| 548 int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl) 549 { 550 struct net *net = xp_net(policy); 551 struct xfrm_policy *pol; 552 struct xfrm_policy *delpol; 553 struct hlist_head *chain; 554 struct hlist_node *entry, *newpos; 555 u32 mark = policy->mark.v & policy->mark.m; 556 557 write_lock_bh(&xfrm_policy_lock); <== use rw lock to protect xfrm polciy database. 558 chain = policy_hash_bysel(net, &policy->selector, policy->family, dir); 559 delpol = NULL; 560 newpos = NULL; 561 hlist_for_each_entry(pol, entry, chain, bydst) { 562 if (pol->type == policy->type && 563 !selector_cmp(&pol->selector, &policy->selector) && 564 (mark & pol->mark.m) == pol->mark.v && 565 xfrm_sec_ctx_match(pol->security, policy->security) && 566 !WARN_ON(delpol)) { 567 if (excl) { 568 write_unlock_bh(&xfrm_policy_lock); 569 return -EEXIST; 570 } 571 delpol = pol; 572 if (policy->priority > pol->priority) <====??? todo 573 continue; 574 } else if (policy->priority >= pol->priority) { 575 newpos = &pol->bydst; 576 continue; 577 } 578 if (delpol) 579 break; 580 } 581 if (newpos) 582 hlist_add_after(newpos, &policy->bydst); 583 else 584 hlist_add_head(&policy->bydst, chain); 585 xfrm_pol_hold(policy); 586 net->xfrm.policy_count[dir]++; 587 atomic_inc(&flow_cache_genid); <== it will be used by flow cache. 588 if (delpol) 589 __xfrm_policy_unlink(delpol, dir); 590 policy->index = delpol ? delpol->index : xfrm_gen_index(net, dir); 591 hlist_add_head(&policy->byidx, net->xfrm.policy_byidx+idx_hash(net, policy->index)); 592 policy->curlft.add_time = get_seconds(); 593 policy->curlft.use_time = 0; 594 if (!mod_timer(&policy->timer, jiffies + HZ)) 595 xfrm_pol_hold(policy); 596 list_add(&policy->walk.all, &net->xfrm.policy_all); 597 write_unlock_bh(&xfrm_policy_lock); 598 599 if (delpol) 600 xfrm_policy_kill(delpol); 601 else if (xfrm_bydst_should_resize(net, dir, NULL)) 602 schedule_work(&net->xfrm.policy_hash_work); 603 604 return 0; 605 } 606 EXPORT_SYMBOL(xfrm_policy_insert);
|