source: EcnlProtoTool/trunk/asp3_dcre/tinet/net/ethernet.c@ 321

Last change on this file since 321 was 321, checked in by coas-nagasima, 7 years ago

文字コードを設定

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 13.1 KB
Line 
1/*
2 * TINET (TCP/IP Protocol Stack)
3 *
4 * Copyright (C) 2001-2009 by Dep. of Computer Science and Engineering
5 * Tomakomai National College of Technology, JAPAN
6 *
7 * 上記著作権者は,以下の (1)~(4) の条件か,Free Software Foundation
8 * によって公表されている GNU General Public License の Version 2 に記
9 * 述されている条件を満たす場合に限り,本ソフトウェア(本ソフトウェア
10 * を改変したものを含む.以下同じ)を使用・複製・改変・再配布(以下,
11 * 利用と呼ぶ)することを無償で許諾する.
12 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
13 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
14 * スコード中に含まれていること.
15 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
16 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
17 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
18 * の無保証規定を掲載すること.
19 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
20 * 用できない形で再配布する場合には,次の条件を満たすこと.
21 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
22 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
23 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
24 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
25 *
26 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
27 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,その適用可能性も
28 * 含めて,いかなる保証も行わない.また,本ソフトウェアの利用により直
29 * 接的または間接的に生じたいかなる損害に関しても,その責任を負わない.
30 *
31 * @(#) $Id$
32 */
33
34/*
35 * Ethernet 処理タスクの本体
36 */
37
38#include <string.h>
39
40#ifdef TARGET_KERNEL_ASP
41
42#include <kernel.h>
43#include <sil.h>
44#include <t_syslog.h>
45#include "kernel_cfg.h"
46
47#endif /* of #ifdef TARGET_KERNEL_ASP */
48
49#ifdef TARGET_KERNEL_JSP
50
51#include <s_services.h>
52#include <t_services.h>
53#include "kernel_id.h"
54
55#endif /* of #ifdef TARGET_KERNEL_JSP */
56
57#include <tinet_defs.h>
58#include <tinet_config.h>
59
60#include <net/if.h>
61#include <net/ethernet.h>
62#include <net/if_llc.h>
63#include <net/if_arp.h>
64#include <net/net.h>
65#include <net/net_var.h>
66#include <net/net_buf.h>
67#include <net/net_timer.h>
68#include <net/net_count.h>
69
70#include <netinet/in.h>
71#include <netinet/in_var.h>
72#include <netinet/if_ether.h>
73#include <netinet6/if6_ether.h>
74#include <netinet6/nd6.h>
75
76#include <net/if_var.h>
77#include <net/if6_var.h>
78
79#ifdef SUPPORT_ETHER
80
81/*
82 * 変数
83 */
84
85#if defined(SUPPORT_INET4)
86
87const uint8_t ether_broad_cast_addr[ETHER_ADDR_LEN] = {
88 UINT_C(0xff), UINT_C(0xff), UINT_C(0xff),
89 UINT_C(0xff), UINT_C(0xff), UINT_C(0xff)
90 };
91
92#endif /* of #if defined(SUPPORT_INET4) */
93
94/*
95 * 変数
96 */
97
98/* ネットワークインタフェース構造体 */
99
100#if defined(SUPPORT_INET4)
101
102static T_IFNET ether_ifnet = {
103 NULL, /* ネットワークインタフェースのソフトウェア情報 */
104 {
105 IPV4_ADDR_LOCAL, /* IPv4 アドレス */
106 IPV4_ADDR_LOCAL_MASK, /* サブネットマスク */
107 },
108 };
109
110#endif /* of #if defined(SUPPORT_INET4) */
111
112#if defined(SUPPORT_INET6)
113
114static T_IFNET ether_ifnet = {
115 NULL, /* ネットワークインタフェースのソフトウェア情報 */
116 {0}, /* IPv6 アドレス情報 */
117 {0}, /* マルチキャスト IPv6 アドレス */
118 0, /* フラグ */
119 };
120
121#endif /* of #if defined(SUPPORT_INET6) */
122
123#ifdef SUPPORT_MIB
124
125/*
126 * SNMP の 管理情報ベース (MIB)
127 */
128
129T_IF_STATS if_stats;
130
131#endif /* of #ifdef SUPPORT_MIB */
132
133#ifdef ETHER_CFG_802_WARNING
134
135/*
136 * 関数
137 */
138
139static void ieee_802_input (T_NET_BUF *input);
140
141/*
142 * ieee_802_input -- IEEE 802.3 入力処理
143 */
144
145static void
146ieee_802_input (T_NET_BUF *input)
147{
148 T_8023MAC_HDR *mhdr;
149 T_8022SNAP_HDR *shdr;
150
151 mhdr = GET_8023MAC_HDR(input);
152 shdr = GET_8022SNAP_HDR(input);
153 syslog(LOG_WARNING, "[ETHER] unexp 802.3 from: %s, proto: 0x%04x.",
154 mac2str(NULL, mhdr->shost), ntohs(*(uint16_t*)&shdr->type));
155 }
156
157#endif /* of #ifdef ETHER_CFG_802_WARNING */
158
159/*
160 * ether_get_ifnet -- ネットワークインタフェース構造体を返す。
161 */
162
163T_IFNET *
164ether_get_ifnet (void)
165{
166 return &ether_ifnet;
167 }
168
169#if defined(SUPPORT_INET6)
170
171/*
172 * ether_in6_resolve_multicast -- イーサネットのマルチキャストアドレスへの変換
173 */
174
175ER
176ether_in6_resolve_multicast (T_ETHER_ADDR *ifaddr, T_IN6_ADDR *maddr)
177{
178 /* マルチキャストアドレスかチェックする。*/
179 if (!IN6_IS_ADDR_MULTICAST(maddr))
180 return E_PAR;
181
182 /* イーサネットのマルチキャストアドレスへの変換 */
183 ether_map_ipv6_multicast(ifaddr, maddr);
184
185 return E_OK;
186 }
187
188#endif /* of #if defined(SUPPORT_INET6) */
189
190/**
191 * Called by a driver when its link goes up
192 */
193void ether_set_link_up(T_IFNET *ether)
194{
195 if (!(ether->flags & IF_FLAG_LINK_UP)) {
196 ether->flags |= IF_FLAG_LINK_UP;
197
198 if (ether->flags & IF_FLAG_UP) {
199#if LWIP_ARP
200 /* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */
201 if (ether->flags & IF_FLAG_ETHARP) {
202 etharp_gratuitous(ether);
203 }
204#endif /* LWIP_ARP */
205 }
206 if (ether->link_callback) {
207 (ether->link_callback)(ether);
208 }
209 }
210}
211
212/**
213 * Called by a driver when its link goes down
214 */
215void ether_set_link_down(T_IFNET *ether)
216{
217 if (ether->flags & IF_FLAG_LINK_UP) {
218 ether->flags &= ~IF_FLAG_LINK_UP;
219 if (ether->link_callback) {
220 (ether->link_callback)(ether);
221 }
222 }
223}
224
225/**
226 * Set callback to be called when link is brought up/down
227 */
228void ether_set_link_callback(ether_status_callback_fn link_callback)
229{
230 ether_ifnet.link_callback = link_callback;
231}
232
233/*
234 * ether_raw_output -- Ethernet インタフェースの出力関数、MAC アドレス解決無し
235 */
236
237ER
238ether_raw_output (T_NET_BUF *output, TMO tmout)
239{
240 ER error = E_OK;
241
242 /* Ethernet 出力キューに投入する。*/
243 if ((error = tsnd_dtq(DTQ_ETHER_OUTPUT, (intptr_t)output, tmout)) != E_OK) {
244 NET_COUNT_ETHER(net_count_ether.out_err_packets, 1);
245 NET_COUNT_MIB(if_stats.ifOutDiscards, 1);
246
247 /* IF でネットワークバッファを開放しないフラグをチェックする。*/
248 if ((output->flags & NB_FLG_NOREL_IFOUT) == 0) {
249 syscall(rel_net_buf(output));
250 }
251 else {
252 output->flags &= (uint8_t)~NB_FLG_NOREL_IFOUT;
253 }
254 IF_ETHER_NIC_RESET(IF_ETHER_NIC_GET_SOFTC());
255 }
256 return error;
257 }
258
259/*
260 * ether_output -- Ethernet インタフェースの出力関数、MAC アドレス解決有り
261 */
262
263ER
264ether_output (T_NET_BUF *output, void *dst, T_IF_ADDR *gw, TMO tmout)
265{
266 T_IF_SOFTC *ic;
267 ER error = E_OK;
268 T_ETHER_HDR *eth;
269
270 /* 送信元 MAC アドレスを設定する。*/
271 ic = IF_ETHER_NIC_GET_SOFTC();
272 eth = GET_ETHER_HDR(output);
273 memcpy(eth->shost, ic->ifaddr.lladdr, ETHER_ADDR_LEN);
274
275 switch(ntohs(eth->type)) {
276
277#if defined(SUPPORT_INET4)
278
279 case ETHER_TYPE_IP: /* IPv4 */
280#ifdef ETHER_CFG_MULTICAST
281 /* マルチキャストアドレスの場合 */
282 if(IN4_IS_ADDR_MULTICAST(*(uint32_t*)dst)){
283 /* イーサネットのマルチキャストアドレスへの変換 */
284 ether_map_ipv4_multicast((T_ETHER_ADDR *)&eth->dhost, *(T_IN4_ADDR*)dst);
285 error = ether_raw_output(output, tmout);
286 break;
287 }
288#endif
289 if (arp_resolve(&ic->ifaddr, output, *(uint32_t*)dst)) { /* true ならアドレス解決済 */
290 error = ether_raw_output(output, tmout);
291 }
292 break;
293
294#endif /* of #if defined(SUPPORT_INET4) */
295
296#if defined(SUPPORT_INET6)
297
298 case ETHER_TYPE_IPV6: /* IPv6 */
299 error = nd6_storelladdr((T_ETHER_ADDR*)GET_ETHER_HDR(output)->dhost,
300 (T_IN6_ADDR*)dst, gw);
301 if (error == E_OK)
302 error = ether_raw_output(output, tmout);
303
304 /* IF でネットワークバッファを開放しないフラグをチェックする。*/
305 else if ((output->flags & NB_FLG_NOREL_IFOUT) == 0) {
306 syscall(rel_net_buf(output));
307 }
308 else {
309 output->flags &= (uint8_t)~NB_FLG_NOREL_IFOUT;
310 }
311 break;
312
313#endif /* of #if defined(SUPPORT_INET6) */
314
315 default:
316 NET_COUNT_MIB(if_stats.ifOutErrors, 1);
317
318 /* IF でネットワークバッファを開放しないフラグをチェックする。*/
319 if ((output->flags & NB_FLG_NOREL_IFOUT) == 0) {
320 syscall(rel_net_buf(output));
321 }
322 else {
323 output->flags &= (uint8_t)~NB_FLG_NOREL_IFOUT;
324 }
325 error = E_PAR;
326 break;
327 }
328
329 if (error != E_OK)
330 NET_COUNT_ETHER(net_count_ether.out_err_packets, 1);
331 return error;
332 }
333
334/*
335 * Ethernet 出力タスク
336 */
337
338void
339ether_output_task(intptr_t exinf)
340{
341 T_IF_SOFTC *ic;
342 T_NET_BUF *output;
343 ID tskid;
344
345 get_tid(&tskid);
346 syslog(LOG_NOTICE, "[ETHER OUTPUT:%d] started.", tskid);
347
348 ic = IF_ETHER_NIC_GET_SOFTC();
349
350 while (true) {
351 while (rcv_dtq(DTQ_ETHER_OUTPUT, (intptr_t*)&output) == E_OK) {
352 NET_COUNT_ETHER(net_count_ether.out_octets, output->len);
353 NET_COUNT_MIB(if_stats.ifOutOctets, output->len + 8);
354 NET_COUNT_ETHER(net_count_ether.out_packets, 1);
355
356#ifdef SUPPORT_MIB
357 if ((*(GET_ETHER_HDR(output)->dhost) & ETHER_MCAST_ADDR) == 0) {
358 NET_COUNT_MIB(if_stats.ifOutUcastPkts, 1);
359 }
360 else {
361 NET_COUNT_MIB(if_stats.ifOutNUcastPkts, 1);
362 }
363#endif /* of #ifdef SUPPORT_MIB */
364
365 syscall(wai_sem(ic->semid_txb_ready));
366
367 IF_ETHER_NIC_START(ic, output);
368
369#ifndef ETHER_NIC_CFG_RELEASE_NET_BUF
370
371 if ((output->flags & NB_FLG_NOREL_IFOUT) == 0) {
372 syscall(rel_net_buf(output));
373 }
374 else {
375 output->flags &= (uint8_t)~NB_FLG_NOREL_IFOUT;
376
377#ifdef SUPPORT_TCP
378 sig_sem(SEM_TCP_POST_OUTPUT);
379#endif /* of #ifdef SUPPORT_TCP */
380 }
381
382#endif /* of #ifndef ETHER_NIC_CFG_RELEASE_NET_BUF */
383
384 }
385 }
386 }
387
388/*
389 * Ethernet 入力タスク
390 */
391
392void
393ether_input_task(intptr_t exinf)
394{
395 T_IF_SOFTC *ic;
396 T_NET_BUF *input;
397 T_ETHER_HDR *eth;
398 ID tskid;
399 uint16_t proto;
400
401 /* ネットワークインタフェース管理を初期化する。*/
402 ifinit();
403
404 /* NIC を初期化する。*/
405 ic = IF_ETHER_NIC_GET_SOFTC();
406 IF_ETHER_NIC_PROBE(ic);
407 IF_ETHER_NIC_INIT(ic);
408
409 /* Ethernet 出力タスクを起動する */
410 syscall(act_tsk(ETHER_OUTPUT_TASK));
411
412 /* ネットワークタイマタスクを起動する */
413 syscall(act_tsk(NET_TIMER_TASK));
414
415 get_tid(&tskid);
416
417 syslog(LOG_NOTICE, "[ETHER INPUT:%2d] started on MAC Addr: %s.",
418 tskid, mac2str(NULL, ic->ifaddr.lladdr));
419
420#if defined(SUPPORT_INET4)
421
422 /* ARP を初期化する。*/
423 arp_init();
424
425#endif /* of #if defined(SUPPORT_INET4) */
426
427 ether_ifnet.ic = ic;
428
429 while (true) {
430 syscall(wai_sem(ic->semid_rxb_ready));
431 if ((input = IF_ETHER_NIC_READ(ic)) != NULL) {
432 NET_COUNT_ETHER(net_count_ether.in_octets, input->len);
433 NET_COUNT_MIB(if_stats.ifInOctets, input->len + 8);
434 NET_COUNT_ETHER(net_count_ether.in_packets, 1);
435 eth = GET_ETHER_HDR(input);
436 proto = ntohs(eth->type);
437
438#ifdef SUPPORT_MIB
439 if ((*eth->dhost & ETHER_MCAST_ADDR) == 0) {
440 NET_COUNT_MIB(if_stats.ifInUcastPkts, 1);
441 }
442 else {
443 NET_COUNT_MIB(if_stats.ifInNUcastPkts, 1);
444 }
445#endif /* of #ifdef SUPPORT_MIB */
446
447#if defined(SUPPORT_INET4) && defined(ETHER_CFG_ACCEPT_ALL)
448
449 if ((*eth->dhost & ETHER_MCAST_ADDR) && *eth->dhost != 0xff) {
450
451#ifdef ETHER_CFG_MCAST_WARNING
452
453 if (proto <= 1500)
454 proto = ntohs(*(uint16_t*)&(GET_8022SNAP_HDR(input)->type));
455 syslog(LOG_WARNING, "[ETHER] mcast addr from: %s, to: %s, proto: 0x%04x.",
456 mac2str(NULL, eth->shost), mac2str(NULL, eth->dhost), proto);
457
458#endif /* of #ifdef ETHER_CFG_MCAST_WARNING */
459
460 NET_COUNT_ETHER(net_count_ether.in_err_packets, 1);
461 NET_COUNT_MIB(if_stats.ifInErrors, 1);
462 syscall(rel_net_buf(input));
463 continue;
464 }
465
466#endif /* of #if defined(SUPPORT_INET4) && defined(ETHER_CFG_ACCEPT_ALL) */
467
468 switch(proto) {
469
470#if defined(SUPPORT_INET4)
471
472 case ETHER_TYPE_IP: /* IP */
473 ip_input(input);
474 break;
475
476 case ETHER_TYPE_ARP: /* ARP */
477 arp_input(&ic->ifaddr, input);
478 break;
479
480#endif /* of #if defined(SUPPORT_INET4) */
481
482#if defined(SUPPORT_INET6)
483
484 case ETHER_TYPE_IPV6: /* IPv6 */
485 ip6_input(input);
486 break;
487
488#endif /* of #if defined(SUPPORT_INET6) */
489
490 default:
491
492#ifdef ETHER_CFG_UNEXP_WARNING
493
494#ifdef ETHER_CFG_802_WARNING
495
496 if (proto <= 1500)
497 ieee_802_input(input);
498 else
499 syslog(LOG_NOTICE, "[ETHER] unexp proto from: %s, proto: 0x%04x.",
500 mac2str(NULL, GET_ETHER_HDR(input)->shost), proto);
501
502#else /* of #ifdef ETHER_CFG_802_WARNING */
503
504 syslog(LOG_INFO, "[ETHER] unexp proto from: %s, proto: 0x%04x.",
505 mac2str(NULL, GET_ETHER_HDR(input)->shost), proto);
506
507#endif /* of #ifdef ETHER_CFG_802_WARNING */
508
509#endif /* of #ifdef ETHER_CFG_UNEXP_WARNING */
510
511 NET_COUNT_ETHER(net_count_ether.in_err_packets, 1);
512 NET_COUNT_MIB(if_stats.ifUnknownProtos, 1);
513 syscall(rel_net_buf(input));
514 break;
515 }
516 }
517 }
518 }
519
520#endif /* of #ifdef SUPPORT_ETHER */
Note: See TracBrowser for help on using the repository browser.