Linux内核网络ip_mkroute_input
来源:互联网 发布:淘宝七天下架什么意思 编辑:程序博客网 时间:2024/05/17 01:49
为输入的IP包生成一个路由项:
ip_mkroute_input
static int ip_mkroute_input(struct sk_buff *skb, struct fib_result *res, const struct flowi4 *fl4, struct in_device *in_dev, __be32 daddr, __be32 saddr, u32 tos){#ifdef CONFIG_IP_ROUTE_MULTIPATH if (res->fi && res->fi->fib_nhs > 1) { int h;
if (unlikely(ip_hdr(skb)->protocol == IPPROTO_ICMP)) h = ip_multipath_icmp_hash(skb); else h = fib_multipath_hash(saddr, daddr); fib_select_multipath(res, h); }#endif
/* create a routing cache entry */ return __mkroute_input(skb, res, in_dev, daddr, saddr, tos);}
/* called in rcu_read_lock() section */static int __mkroute_input(struct sk_buff *skb, const struct fib_result *res, struct in_device *in_dev, __be32 daddr, __be32 saddr, u32 tos){ struct fib_nh_exception *fnhe; struct rtable *rth; int err; struct in_device *out_dev; bool do_cache; u32 itag = 0;
/* get a working reference to the output device */ out_dev = __in_dev_get_rcu(FIB_RES_DEV(*res)); if (!out_dev) { net_crit_ratelimited("Bug in ip_route_input_slow(). Please report.\n"); return -EINVAL; }
err = fib_validate_source(skb, saddr, daddr, tos, FIB_RES_OIF(*res), in_dev->dev, in_dev, &itag); if (err < 0) { ip_handle_martian_source(in_dev->dev, in_dev, skb, daddr, saddr);
goto cleanup; }
do_cache = res->fi && !itag; if (out_dev == in_dev && err && IN_DEV_TX_REDIRECTS(out_dev) && skb->protocol == htons(ETH_P_IP) && (IN_DEV_SHARED_MEDIA(out_dev) || inet_addr_onlink(out_dev, saddr, FIB_RES_GW(*res)))) IPCB(skb)->flags |= IPSKB_DOREDIRECT;
if (skb->protocol != htons(ETH_P_IP)) { /* Not IP (i.e. ARP). Do not create route, if it is * invalid for proxy arp. DNAT routes are always valid. * * Proxy arp feature have been extended to allow, ARP * replies back to the same interface, to support * Private VLAN switch technologies. See arp.c. */ if (out_dev == in_dev && IN_DEV_PROXY_ARP_PVLAN(in_dev) == 0) { err = -EINVAL; goto cleanup; } }
fnhe = find_exception(&FIB_RES_NH(*res), daddr); if (do_cache) { if (fnhe) { rth = rcu_dereference(fnhe->fnhe_rth_input); if (rth && rth->dst.expires && time_after(jiffies, rth->dst.expires)) { ip_del_fnhe(&FIB_RES_NH(*res), daddr); fnhe = NULL; } else { goto rt_cache; } }
rth = rcu_dereference(FIB_RES_NH(*res).nh_rth_input);
rt_cache: if (rt_cache_valid(rth)) { skb_dst_set_noref(skb, &rth->dst); goto out; } }
rth = rt_dst_alloc(out_dev->dev, 0, res->type, IN_DEV_CONF_GET(in_dev, NOPOLICY), IN_DEV_CONF_GET(out_dev, NOXFRM), do_cache); if (!rth) { err = -ENOBUFS; goto cleanup; }
rth->rt_is_input = 1; if (res->table) rth->rt_table_id = res->table->tb_id; RT_CACHE_STAT_INC(in_slow_tot);
rth->dst.input = ip_forward;
rt_set_nexthop(rth, daddr, res, fnhe, res->fi, res->type, itag); if (lwtunnel_output_redirect(rth->dst.lwtstate)) { rth->dst.lwtstate->orig_output = rth->dst.output; rth->dst.output = lwtunnel_output; } if (lwtunnel_input_redirect(rth->dst.lwtstate)) { rth->dst.lwtstate->orig_input = rth->dst.input; rth->dst.input = lwtunnel_input; } skb_dst_set(skb, &rth->dst);out: err = 0; cleanup: return err;}
- Linux内核网络ip_mkroute_input
- linux内核网络栈
- Linux内核分析-网络
- linux网络内核结构
- Linux 内核网络优化
- Linux 内核网络参数
- Linux 内核网络优化
- linux内核网络栈
- Linux内核网络参数
- 精通Linux内核网络
- linux内核网络子系统
- Linux内核--网络内核实现分析
- 深入Linux内核网络堆栈
- 深入Linux内核网络堆栈
- 深入Linux内核网络堆栈
- 深入Linux内核网络堆栈
- .linux内核网络栈代码
- 深入Linux内核网络堆栈
- Spark(一): 基本架构及原理
- FFTW中文说明
- HTTP基础认证Basic Authentication
- 斐波那契数列的几种解法
- MySQL to Redis
- Linux内核网络ip_mkroute_input
- 关于关键词提取,摘要提取的,及文本相似总结
- UIImageView上添加Button不能响应点击事件
- 在shell中把ls的输出存进一个数组变量中
- 合并两个排序列表
- 给Nginx配置一个自签名的SSL证书 【转】
- java自定义注解
- 使用pip安装软件时报pip is configured with locations that require TLS/SSL, however the ssl modul错误
- Java基础知识-文件(七)