Contiki-NG
csma.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010, Swedish Institute of Computer Science.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * This file is part of the Contiki operating system.
30  *
31  */
32 
33 /**
34  * \file
35 * The 802.15.4 standard CSMA protocol (nonbeacon-enabled)
36  * \author
37  * Adam Dunkels <adam@sics.se>
38  * Simon Duquennoy <simon.duquennoy@inria.fr>
39  */
40 
41 #include "net/mac/csma/csma.h"
43 #include "net/mac/mac-sequence.h"
44 #include "net/packetbuf.h"
45 #include "net/netstack.h"
46 
47 /* Log configuration */
48 #include "sys/log.h"
49 #define LOG_MODULE "CSMA"
50 #define LOG_LEVEL LOG_LEVEL_MAC
51 
52 
53 static void
54 init_sec(void)
55 {
56 #if LLSEC802154_USES_AUX_HEADER
57  if(packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL) ==
58  PACKETBUF_ATTR_SECURITY_LEVEL_DEFAULT) {
59  packetbuf_set_attr(PACKETBUF_ATTR_SECURITY_LEVEL,
60  CSMA_LLSEC_SECURITY_LEVEL);
61  }
62 #endif
63 }
64 /*---------------------------------------------------------------------------*/
65 static void
66 send_packet(mac_callback_t sent, void *ptr)
67 {
68 
69  init_sec();
70 
71  csma_output_packet(sent, ptr);
72 }
73 /*---------------------------------------------------------------------------*/
74 static void
75 input_packet(void)
76 {
77 #if CSMA_SEND_SOFT_ACK
78  uint8_t ackdata[CSMA_ACK_LEN];
79 #endif
80 
81  if(packetbuf_datalen() == CSMA_ACK_LEN) {
82  /* Ignore ack packets */
83  LOG_DBG("ignored ack\n");
84  } else if(csma_security_parse_frame() < 0) {
85  LOG_ERR("failed to parse %u\n", packetbuf_datalen());
86  } else if(!linkaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
89  LOG_WARN("not for us\n");
90  } else if(linkaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_SENDER), &linkaddr_node_addr)) {
91  LOG_WARN("frame from ourselves\n");
92  } else {
93  int duplicate = 0;
94 
95  /* Check for duplicate packet. */
96  duplicate = mac_sequence_is_duplicate();
97  if(duplicate) {
98  /* Drop the packet. */
99  LOG_WARN("drop duplicate link layer packet from ");
100  LOG_WARN_LLADDR(packetbuf_addr(PACKETBUF_ADDR_SENDER));
101  LOG_WARN_(", seqno %u\n", packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO));
102  } else {
104  }
105 
106 #if CSMA_SEND_SOFT_ACK
107  if(packetbuf_attr(PACKETBUF_ATTR_MAC_ACK)) {
108  ackdata[0] = FRAME802154_ACKFRAME;
109  ackdata[1] = 0;
110  ackdata[2] = ((uint8_t *)packetbuf_hdrptr())[2];
111  NETSTACK_RADIO.send(ackdata, CSMA_ACK_LEN);
112  }
113 #endif /* CSMA_SEND_SOFT_ACK */
114  if(!duplicate) {
115  LOG_INFO("received packet from ");
116  LOG_INFO_LLADDR(packetbuf_addr(PACKETBUF_ADDR_SENDER));
117  LOG_INFO_(", seqno %u, len %u\n", packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO), packetbuf_datalen());
118  NETSTACK_NETWORK.input();
119  }
120  }
121 }
122 /*---------------------------------------------------------------------------*/
123 static int
124 on(void)
125 {
126  return NETSTACK_RADIO.on();
127 }
128 /*---------------------------------------------------------------------------*/
129 static int
130 off(void)
131 {
132  return NETSTACK_RADIO.off();
133 }
134 /*---------------------------------------------------------------------------*/
135 static void
136 init(void)
137 {
138  radio_value_t radio_max_payload_len;
139 
140  /* Check that the radio can correctly report its max supported payload */
141  if(NETSTACK_RADIO.get_value(RADIO_CONST_MAX_PAYLOAD_LEN, &radio_max_payload_len) != RADIO_RESULT_OK) {
142  LOG_ERR("! radio does not support getting RADIO_CONST_MAX_PAYLOAD_LEN. Abort init.\n");
143  return;
144  }
145 
146 #if CSMA_SEND_SOFT_ACK
147  radio_value_t radio_rx_mode;
148 
149  /* Disable radio driver's autoack */
150  if(NETSTACK_RADIO.get_value(RADIO_PARAM_RX_MODE, &radio_rx_mode) != RADIO_RESULT_OK) {
151  LOG_WARN("radio does not support getting RADIO_PARAM_RX_MODE\n");
152  } else {
153  /* Unset autoack */
154  radio_rx_mode &= ~RADIO_RX_MODE_AUTOACK;
155  if(NETSTACK_RADIO.set_value(RADIO_PARAM_RX_MODE, radio_rx_mode) != RADIO_RESULT_OK) {
156  LOG_WARN("radio does not support setting RADIO_PARAM_RX_MODE\n");
157  }
158  }
159 #endif
160 
161 
162 #if LLSEC802154_USES_AUX_HEADER
163 #ifdef CSMA_LLSEC_DEFAULT_KEY0
164  uint8_t key[16] = CSMA_LLSEC_DEFAULT_KEY0;
165  csma_security_set_key(0, key);
166 #endif
167 #endif /* LLSEC802154_USES_AUX_HEADER */
168  csma_output_init();
169  on();
170 }
171 /*---------------------------------------------------------------------------*/
172 static int
173 max_payload(void)
174 {
175  int framer_hdrlen;
176  radio_value_t max_radio_payload_len;
177  radio_result_t res;
178 
179  init_sec();
180 
181  framer_hdrlen = NETSTACK_FRAMER.length();
182 
183  res = NETSTACK_RADIO.get_value(RADIO_CONST_MAX_PAYLOAD_LEN,
184  &max_radio_payload_len);
185 
186  if(res == RADIO_RESULT_NOT_SUPPORTED) {
187  LOG_ERR("Failed to retrieve max radio driver payload length\n");
188  return 0;
189  }
190 
191  if(framer_hdrlen < 0) {
192  /* Framing failed, we assume the maximum header length */
193  framer_hdrlen = CSMA_MAC_MAX_HEADER;
194  }
195 
196  return MIN(max_radio_payload_len, PACKETBUF_SIZE)
197  - framer_hdrlen
198  - LLSEC802154_PACKETBUF_MIC_LEN();
199 }
200 /*---------------------------------------------------------------------------*/
201 const struct mac_driver csma_driver = {
202  "CSMA",
203  init,
204  send_packet,
205  input_packet,
206  on,
207  off,
208  max_payload,
209 };
210 /*---------------------------------------------------------------------------*/
The parameter is not supported.
Definition: radio.h:473
int(* on)(void)
Turn the MAC layer on.
Definition: mac.h:75
The 802.15.4 standard CSMA protocol (nonbeacon-enabled).
The structure of a MAC protocol driver in Contiki.
Definition: mac.h:62
The 802.15.4 standard CSMA protocol (nonbeacon-enabled)
static void send_packet(linkaddr_t *dest)
This function is called by the 6lowpan code to send out a packet.
Definition: sicslowpan.c:1537
int mac_sequence_is_duplicate(void)
Tell whether the packetbuf is a duplicate packet.
Definition: mac-sequence.c:72
The parameter was set/read successfully.
Definition: radio.h:472
int radio_value_t
Each radio has a set of parameters that designate the current configuration and state of the radio...
Definition: radio.h:88
Header file for MAC sequence numbers management
int(* off)(void)
Turn the MAC layer off.
Definition: mac.h:78
uint16_t packetbuf_datalen(void)
Get the length of the data in the packetbuf.
Definition: packetbuf.c:155
linkaddr_t linkaddr_node_addr
The link-layer address of the node.
Definition: linkaddr.c:48
Radio receiver mode determines if the radio has address filter (RADIO_RX_MODE_ADDRESS_FILTER) and aut...
Definition: radio.h:173
#define PACKETBUF_SIZE
The size of the packetbuf, in bytes.
Definition: packetbuf.h:67
int packetbuf_holds_broadcast(void)
Checks whether the current packet is a broadcast.
Definition: packetbuf.c:231
enum radio_result_e radio_result_t
Radio return values when setting or getting radio parameters.
int linkaddr_cmp(const linkaddr_t *addr1, const linkaddr_t *addr2)
Compare two link-layer addresses.
Definition: linkaddr.c:69
#define RADIO_RX_MODE_AUTOACK
Enable automatic transmission of ACK frames.
Definition: radio.h:448
void * packetbuf_hdrptr(void)
Get a pointer to the header in the packetbuf, for outbound packets.
Definition: packetbuf.c:149
void(* init)(void)
Initialize the MAC driver.
Definition: mac.h:66
Header file for the Packet buffer (packetbuf) management
Include file for the Contiki low-layer network stack (NETSTACK)
void mac_sequence_register_seqno(void)
Register the sequence number of the packetbuf.
Definition: mac-sequence.c:101
int(* max_payload)(void)
Read out estimated max payload size based on payload in packetbuf.
Definition: mac.h:81
Stores data about an incoming packet.
Definition: tsch-types.h:149
Header file for the logging system