1 /*
2 *
3 * Copyright (c) 2003 The Regents of the University of California. All
4 * rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * - Neither the name of the University nor the names of its
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS''
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
19 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
21 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
25 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 */
30
31
32 /*
33 * rnc_lower.c: The "lower" half of rnc, i.e. handling the link
34 * layer interfaces underneath the daemon that we use to send the
35 * packets.
36 *
37 * $Id: rnc_lower.c,v 1.10 2003-07-11 22:29:54 cerpa Exp $
38 */
39
40 char rnc_lower_c_cvsid[] = "$Id: rnc_lower.c,v 1.10 2003-07-11 22:29:54 cerpa Exp $";
41
42 #include <stdio.h>
43 #include <stdlib.h>
44
45 #include "link/link.h"
46 #include "rnc_i.h"
47
48
49 /*******************************************************************/
50
51
52 /*
53 * This callback is called whenever a packet arrives up from one of
54 * the underlying datalink interfaces
55 */
56 static int rnc_receiver(link_pkt_t *link_pkt, ssize_t data_len, link_context_t *link)
57 {
58 rnc_state_t *f = (rnc_state_t *) link_opts(link)->data;
59 rnc_pkt_t *rnc_pkt = (rnc_pkt_t *) link_pkt->data;
60
61 // Make sure the packet has the right packet type. Since we
62 // specified the desired packet type when we registered to receive
63 // packets, this test should never fail.
64 if (link_pkt->type != PKT_TYPE_RNC) {
65 elog(LOG_WARNING, "got a packet not meant for us - filter failed!");
66 goto done;
67 }
68
69 // Make sure the data portion of the packet is at least the size of
70 // a rnc packet header
71 if (data_len < sizeof(rnc_pkt_t)) {
72 elog(LOG_ERR, "got a short rnc packet (%d bytes < %d)!", data_len,
73 sizeof(rnc_pkt_t));
74 goto done;
75 }
76
77 // We now know that the data pointed to by rnc_pkt is valid
78 switch( rnc_pkt->sub_type) {
79 case RNC_DATA:
80 elog(LOG_DEBUG(4), "got rnc data packet");
81 rnc_handle_data_pkt(f, link_pkt, data_len);
82 break;
83 case RNC_ACK:
84 elog(LOG_DEBUG(4), "got rnc ack packet");
85 rnc_handle_ack_pkt(f, link_pkt, data_len);
86 break;
87 default:
88 elog(LOG_ERR, "got rnc packet with an unknown subtype %d", rnc_pkt->sub_type);
89 }
90
91 done:
92 free(link_pkt);
93 return EVENT_RENEW;
94 }
95
96
97 /*
98 * This function opens one of the underlying transport devices used by
99 * the rnc daemon (e.g., a basic datalink such as motenic)
100 */
101 void rnc_open_link(rnc_state_t *f, int link_index)
102 {
103 rnc_iface_t *i;
104
105 // make sure we don't have too many interfaces open
106 if (f->num_ifaces >= MAX_IFACES) {
107 elog(LOG_ERR, "can't open link interface: too many interfaces!");
108 exit(1);
109 }
110
111 // get a pointer to the next available iface struct
112 i = &(f->iface[f->num_ifaces]);
113
114 // set options for this link
115 memset(i, 0, sizeof(rnc_iface_t));
116 i->if_opts.link_index = link_index;
117 i->if_opts.pkt_type = PKT_TYPE_RNC;
118 // Make the queues large enough to handle retransmission storms
119 i->if_opts.q_opts.outq_len = 300;
120 i->if_opts.q_opts.inq_len = 300;
121 i->if_opts.receive = rnc_receiver;
122 i->if_opts.data = f;
123
124 // try to open it
125 if (link_open(&i->if_opts, &i->if_context) < 0) {
126 elog(LOG_CRIT, "can't open %s: %m", link_name(&i->if_opts));
127 exit(1);
128 }
129
130 // Open succeeded - increment interface count
131 f->num_ifaces++;
132 elog(LOG_NOTICE, "opened lower interface %d: %s", f->num_ifaces, link_name(&i->if_opts));
133 }
134
135
136 /*
137 * Send a link_pkt to all interfaces opened by the function above
138 */
139 void rnc_send_to_all(rnc_state_t *f, link_pkt_t *pkt, int data_len)
140 {
141 int i;
142 uint32_t seqnum;
143 rnc_pkt_t *p=(rnc_pkt_t *)(pkt->data);
144 rnc_data_pkt_t *d=(rnc_data_pkt_t *)(p->next_hdr);
145
146 if (p->sub_type==RNC_DATA) {
147 seqnum=d->seq_num;
148 elog(LOG_NOTICE, "Source %d sending packet %d\n",
149 my_node_id, seqnum);
150 } else {
151 elog(LOG_NOTICE, "Source %d sending ACK packet\n", my_node_id);
152 }
153
154 elog(LOG_DEBUG(4), "sending; %d interfaces", f->num_ifaces);
155
156 for (i = 0; i < f->num_ifaces; i++) {
157 elog(LOG_DEBUG(4), "sending to %s",
158 link_name(link_opts(f->iface[i].if_context)));
159
160 if (link_send(f->iface[i].if_context, pkt, data_len) < 0)
161 elog(LOG_WARNING, "sending to %s: %m",
162 link_name(&(f->iface[i].if_opts)));
163 }
164 }
165
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.