From d47d1b1684180ae9c44545cd473d6bdfb5c2a390 Mon Sep 17 00:00:00 2001 From: Jeremy Lakeman Date: Tue, 4 Jun 2013 12:12:45 +0930 Subject: [PATCH] Split network destination structure from interface structure --- overlay_buffer.c | 4 +-- overlay_buffer.h | 2 +- overlay_interface.c | 49 +++++++++++++------------- overlay_mdp.c | 2 +- overlay_packetformats.c | 4 +-- overlay_payload.c | 2 +- overlay_queue.c | 25 +++++++------- route_link.c | 12 +++---- serval.h | 76 ++++++++++++++++++++++------------------- 9 files changed, 93 insertions(+), 83 deletions(-) diff --git a/overlay_buffer.c b/overlay_buffer.c index 993ff906..ceaf78cc 100644 --- a/overlay_buffer.c +++ b/overlay_buffer.c @@ -228,7 +228,7 @@ unsigned char *_ob_append_space(struct __sourceloc __whence, struct overlay_buff return r; } -int _ob_append_bytes(struct __sourceloc __whence, struct overlay_buffer *b, unsigned char *bytes, int count) +int _ob_append_bytes(struct __sourceloc __whence, struct overlay_buffer *b, const unsigned char *bytes, int count) { if (_ob_makespace(__whence, b,count)) return WHY("ob_makespace() failed"); @@ -263,7 +263,7 @@ int _ob_append_ui32(struct __sourceloc __whence, struct overlay_buffer *b, uint3 int _ob_append_ui64(struct __sourceloc __whence, struct overlay_buffer *b, uint64_t v) { - if (ob_makespace(__whence, b, 8)) return WHY("ob_makespace() failed"); + if (_ob_makespace(__whence, b, 8)) return WHY("ob_makespace() failed"); b->bytes[b->position] = (v >> 56) & 0xFF; b->bytes[b->position+1] = (v >> 48) & 0xFF; b->bytes[b->position+2] = (v >> 40) & 0xFF; diff --git a/overlay_buffer.h b/overlay_buffer.h index f1bc3e11..8c93f01a 100644 --- a/overlay_buffer.h +++ b/overlay_buffer.h @@ -55,7 +55,7 @@ int _ob_makespace(struct __sourceloc whence, struct overlay_buffer *b,int bytes) int ob_set(struct overlay_buffer *b, int ofs, unsigned char byte); int _ob_append_byte(struct __sourceloc whence, struct overlay_buffer *b,unsigned char byte); -int _ob_append_bytes(struct __sourceloc whence, struct overlay_buffer *b,unsigned char *bytes,int count); +int _ob_append_bytes(struct __sourceloc whence, struct overlay_buffer *b,const unsigned char *bytes,int count); int _ob_append_buffer(struct __sourceloc whence, struct overlay_buffer *b,struct overlay_buffer *s); unsigned char *_ob_append_space(struct __sourceloc whence, struct overlay_buffer *b,int count); int _ob_append_ui16(struct __sourceloc whence, struct overlay_buffer *b, uint16_t v); diff --git a/overlay_interface.c b/overlay_interface.c index 75d0bcdb..354ef187 100644 --- a/overlay_interface.c +++ b/overlay_interface.c @@ -65,7 +65,7 @@ static void overlay_interface_close(overlay_interface *interface){ link_interface_down(interface); enum_subscribers(NULL, mark_subscriber_down, interface); - INFOF("Interface %s addr %s is down", interface->name, inet_ntoa(interface->broadcast_address.sin_addr)); + INFOF("Interface %s addr %s is down", interface->name, inet_ntoa(interface->destination.address.sin_addr)); unschedule(&interface->alarm); unwatch(&interface->alarm); close(interface->alarm.poll.fd); @@ -320,7 +320,7 @@ overlay_interface_init_socket(int interface_index) const struct sockaddr *addr = (const struct sockaddr *)&interface->address; - interface->alarm.poll.fd = overlay_bind_socket(addr, sizeof(interface->broadcast_address), interface->name); + interface->alarm.poll.fd = overlay_bind_socket(addr, sizeof(interface->destination.address), interface->name); if (interface->alarm.poll.fd<0){ interface->state=INTERFACE_STATE_DOWN; return WHYF("Failed to bind interface %s", interface->name); @@ -328,8 +328,8 @@ overlay_interface_init_socket(int interface_index) if (config.debug.packetrx || config.debug.io) { char srctxt[INET_ADDRSTRLEN]; - if (inet_ntop(AF_INET, (const void *)&interface->broadcast_address.sin_addr, srctxt, INET_ADDRSTRLEN)) - DEBUGF("Bound to %s:%d", srctxt, ntohs(interface->broadcast_address.sin_port)); + if (inet_ntop(AF_INET, (const void *)&interface->destination.address.sin_addr, srctxt, INET_ADDRSTRLEN)) + DEBUGF("Bound to %s:%d", srctxt, ntohs(interface->destination.address.sin_port)); } interface->alarm.poll.events=POLLIN; @@ -382,13 +382,14 @@ overlay_interface_init(const char *name, struct in_addr src_addr, struct in_addr interface->prefer_unicast = ifconfig->prefer_unicast; interface->default_route = ifconfig->default_route; interface->socket_type = ifconfig->socket_type; - interface->encapsulation = ifconfig->encapsulation; + interface->destination.interface = interface; + interface->destination.encapsulation = ifconfig->encapsulation; interface->uartbps = ifconfig->uartbps; interface->ctsrts = ifconfig->ctsrts; /* Pick a reasonable default MTU. This will ultimately get tuned by the bandwidth and other properties of the interface */ - interface->mtu=1200; + interface->destination.mtu=1200; interface->state=INTERFACE_STATE_DOWN; interface->alarm.poll.fd=0; interface->debug = ifconfig->debug; @@ -446,11 +447,11 @@ overlay_interface_init(const char *name, struct in_addr src_addr, struct in_addr INFOF("Interface %s is running tickless", name); if (tick_ms<0) - return WHYF("No tick interval %d specified for interface %s", interface->tick_ms, name); + return WHYF("No tick interval specified for interface %s", name); - interface->tick_ms = tick_ms; + interface->destination.tick_ms = tick_ms; - limit_init(&interface->transfer_limit, packet_interval); + limit_init(&interface->destination.transfer_limit, packet_interval); interface->address.sin_family=AF_INET; interface->address.sin_port = htons(ifconfig->port); @@ -458,9 +459,9 @@ overlay_interface_init(const char *name, struct in_addr src_addr, struct in_addr interface->netmask=ifconfig->dummy_netmask; - interface->broadcast_address.sin_family=AF_INET; - interface->broadcast_address.sin_port = htons(ifconfig->port); - interface->broadcast_address.sin_addr.s_addr = interface->address.sin_addr.s_addr | ~interface->netmask.s_addr; + interface->destination.address.sin_family=AF_INET; + interface->destination.address.sin_port = htons(ifconfig->port); + interface->destination.address.sin_addr.s_addr = interface->address.sin_addr.s_addr | ~interface->netmask.s_addr; interface->alarm.function = overlay_interface_poll; interface_poll_stats.name="overlay_interface_poll"; @@ -468,7 +469,7 @@ overlay_interface_init(const char *name, struct in_addr src_addr, struct in_addr if (ifconfig->socket_type==SOCK_DGRAM){ interface->address.sin_addr = src_addr; - interface->broadcast_address.sin_addr = broadcast; + interface->destination.address.sin_addr = broadcast; interface->netmask = netmask; interface->local_echo = 1; @@ -523,7 +524,9 @@ overlay_interface_init(const char *name, struct in_addr src_addr, struct in_addr directory_registration(); - INFOF("Allowing a maximum of %d packets every %lldms", interface->transfer_limit.burst_size, interface->transfer_limit.burst_length); + INFOF("Allowing a maximum of %d packets every %lldms", + interface->destination.transfer_limit.burst_size, + interface->destination.transfer_limit.burst_length); overlay_interface_count++; return 0; @@ -600,7 +603,7 @@ static int should_drop(struct overlay_interface *interface, struct sockaddr_in a if (memcmp(&addr, &interface->address, sizeof(addr))==0){ return interface->drop_unicasts; } - if (memcmp(&addr, &interface->broadcast_address, sizeof(addr))==0){ + if (memcmp(&addr, &interface->destination.address, sizeof(addr))==0){ if (interface->drop_broadcasts == 0) return 0; if (interface->drop_broadcasts >= 100) @@ -757,13 +760,13 @@ static void overlay_interface_poll(struct sched_ent *alarm) alarm->alarm=-1; time_ms_t now = gettime_ms(); - if (interface->state==INTERFACE_STATE_UP && interface->tick_ms>0){ - if (now >= interface->last_tx+interface->tick_ms) + if (interface->state==INTERFACE_STATE_UP && interface->destination.tick_ms>0){ + if (now >= interface->destination.last_tx+interface->destination.tick_ms) overlay_send_tick_packet(interface); - alarm->alarm=interface->last_tx+interface->tick_ms; - alarm->deadline=alarm->alarm+interface->tick_ms/2; + alarm->alarm=interface->destination.last_tx+interface->destination.tick_ms; + alarm->deadline=alarm->alarm+interface->destination.tick_ms/2; } - + switch(interface->socket_type){ case SOCK_DGRAM: case SOCK_STREAM: @@ -817,7 +820,7 @@ overlay_broadcast_ensemble(overlay_interface *interface, struct sockaddr_in *recipientaddr, unsigned char *bytes,int len) { - interface->last_tx = gettime_ms(); + interface->destination.last_tx = gettime_ms(); if (config.debug.packettx) { @@ -969,7 +972,7 @@ overlay_interface_register(char *name, int broadcast_match = 0; int name_match =0; - if (overlay_interfaces[i].broadcast_address.sin_addr.s_addr == broadcast.s_addr) + if (overlay_interfaces[i].destination.address.sin_addr.s_addr == broadcast.s_addr) broadcast_match = 1; name_match = !strcasecmp(overlay_interfaces[i].name, name); @@ -998,7 +1001,7 @@ overlay_interface_register(char *name, if (found_interface>=0){ // try to reactivate the existing interface overlay_interfaces[found_interface].address.sin_addr = addr; - overlay_interfaces[found_interface].broadcast_address.sin_addr = broadcast; + overlay_interfaces[found_interface].destination.address.sin_addr = broadcast; overlay_interfaces[found_interface].netmask = mask; return re_init_socket(found_interface); } diff --git a/overlay_mdp.c b/overlay_mdp.c index 190ea96b..c314b220 100644 --- a/overlay_mdp.c +++ b/overlay_mdp.c @@ -999,7 +999,7 @@ void overlay_mdp_poll(struct sched_ent *alarm) scans[i].interface = interface; scans[i].current = ntohl(interface->address.sin_addr.s_addr & interface->netmask.s_addr)+1; - scans[i].last = ntohl(interface->broadcast_address.sin_addr.s_addr)-1; + scans[i].last = ntohl(interface->destination.address.sin_addr.s_addr)-1; if (scans[i].last - scans[i].current>0x10000){ INFOF("Skipping scan on interface %s as the address space is too large",interface->name); continue; diff --git a/overlay_packetformats.c b/overlay_packetformats.c index 536e97d0..b3b53eda 100644 --- a/overlay_packetformats.c +++ b/overlay_packetformats.c @@ -322,7 +322,7 @@ int parseEnvelopeHeader(struct decode_context *context, struct overlay_interface } /* Note the probe payload must be queued before any SID/SAS request so we can force the packet to have a full sid */ - if (addr && (context->sender->last_probe==0 || now - context->sender->last_probe > interface->tick_ms*10)) + if (addr && (context->sender->last_probe==0 || now - context->sender->last_probe > interface->destination.tick_ms*10)) overlay_send_probe(context->sender, *addr, interface, OQ_MESH_MANAGEMENT); link_received_packet(context->sender, interface, context->sender_interface, sender_seq, packet_flags & PACKET_UNICAST); @@ -336,7 +336,7 @@ int parseEnvelopeHeader(struct decode_context *context, struct overlay_interface if (packet_flags & PACKET_UNICAST) context->addr=*addr; else - context->addr=interface->broadcast_address; + context->addr=interface->destination.address; } RETURN(0); OUT(); diff --git a/overlay_payload.c b/overlay_payload.c index a138652e..6a6df367 100644 --- a/overlay_payload.c +++ b/overlay_payload.c @@ -110,7 +110,7 @@ int overlay_frame_append_payload(struct decode_context *context, overlay_interfa p->destination, p->source)) goto cleanup; - if (interface->encapsulation == ENCAP_OVERLAY){ + if (interface->destination.encapsulation == ENCAP_OVERLAY){ if (ob_append_ui16(b, ob_position(p->payload))) goto cleanup; } diff --git a/overlay_queue.c b/overlay_queue.c index 739f66b4..25db2887 100644 --- a/overlay_queue.c +++ b/overlay_queue.c @@ -282,10 +282,11 @@ overlay_init_packet(struct outgoing_packet *packet, struct subscriber *destinati if (unicast) packet->unicast_subscriber = destination; else - packet->seq = interface->sequence_number = (interface->sequence_number + 1)&0xFFFF; - ob_limitsize(packet->buffer, packet->interface->mtu); + packet->seq = interface->destination.sequence_number = (interface->destination.sequence_number + 1)&0xFFFF; + ob_limitsize(packet->buffer, packet->interface->destination.mtu); - overlay_packet_init_header(packet_version, interface->encapsulation, &packet->context, packet->buffer, + overlay_packet_init_header(packet_version, interface->destination.encapsulation, + &packet->context, packet->buffer, destination, unicast, packet->i, packet->seq); packet->header_length = ob_position(packet->buffer); if (config.debug.overlayframes) @@ -334,7 +335,7 @@ overlay_calc_queue_time(overlay_txqueue *queue, struct overlay_frame *frame){ // don't include interfaces which are currently transmitting using a serial buffer if (frame->interface->tx_bytes_pending>0) return 0; - next_allowed_packet = limit_next_allowed(&frame->interface->transfer_limit); + next_allowed_packet = limit_next_allowed(&frame->interface->destination.transfer_limit); }else{ // check all interfaces int i; @@ -345,7 +346,7 @@ overlay_calc_queue_time(overlay_txqueue *queue, struct overlay_frame *frame){ if ((!frame->destination) && (frame->interface_sent_sequence[i]==FRAME_DONT_SEND || link_state_interface_oldest_neighbour(&overlay_interfaces[i])<0)) continue; - time_ms_t next_packet = limit_next_allowed(&overlay_interfaces[i].transfer_limit); + time_ms_t next_packet = limit_next_allowed(&overlay_interfaces[i].destination.transfer_limit); if (next_packet < frame->interface_dont_send_until[i]) next_packet = frame->interface_dont_send_until[i]; if (next_allowed_packet==0||next_packet < next_allowed_packet) @@ -436,7 +437,7 @@ overlay_stuff_packet(struct outgoing_packet *packet, overlay_txqueue *queue, tim frame->recvaddr = frame->next_hop->address; frame->unicast = 1; }else - frame->recvaddr = frame->interface->broadcast_address; + frame->recvaddr = frame->interface->destination.address; // degrade packet version if required to reach the destination if (frame->packet_version > frame->next_hop->max_packet_version) @@ -450,7 +451,7 @@ overlay_stuff_packet(struct outgoing_packet *packet, overlay_txqueue *queue, tim if (frame->interface_sent_sequence[packet->i]==FRAME_DONT_SEND || frame->interface_dont_send_until[packet->i] >now) goto skip; frame->interface = packet->interface; - frame->recvaddr = packet->interface->broadcast_address; + frame->recvaddr = packet->interface->destination.address; }else{ // find an interface that we haven't broadcast on yet @@ -465,11 +466,11 @@ overlay_stuff_packet(struct outgoing_packet *packet, overlay_txqueue *queue, tim keep=1; if (frame->interface_dont_send_until[i] >now) continue; - time_ms_t next_allowed = limit_next_allowed(&overlay_interfaces[i].transfer_limit); + time_ms_t next_allowed = limit_next_allowed(&overlay_interfaces[i].destination.transfer_limit); if (next_allowed > now) continue; frame->interface = &overlay_interfaces[i]; - frame->recvaddr = overlay_interfaces[i].broadcast_address; + frame->recvaddr = overlay_interfaces[i].destination.address; break; } @@ -493,7 +494,7 @@ overlay_stuff_packet(struct outgoing_packet *packet, overlay_txqueue *queue, tim } // can we send a packet on this interface now? - if (limit_is_allowed(&frame->interface->transfer_limit)) + if (limit_is_allowed(&frame->interface->destination.transfer_limit)) goto skip; if (frame->source_full) @@ -504,7 +505,7 @@ overlay_stuff_packet(struct outgoing_packet *packet, overlay_txqueue *queue, tim }else{ // is this packet going our way? if (frame->interface!=packet->interface || - frame->interface->encapsulation==ENCAP_SINGLE || + frame->interface->destination.encapsulation==ENCAP_SINGLE || frame->packet_version!=packet->packet_version || memcmp(&packet->dest, &frame->recvaddr, sizeof(packet->dest))!=0){ goto skip; @@ -636,7 +637,7 @@ int overlay_send_tick_packet(struct overlay_interface *interface){ struct outgoing_packet packet; bzero(&packet, sizeof(struct outgoing_packet)); packet.seq=-1; - overlay_init_packet(&packet, NULL, 0, 0, interface, interface->broadcast_address); + overlay_init_packet(&packet, NULL, 0, 0, interface, interface->destination.address); overlay_fill_send_packet(&packet, gettime_ms()); return 0; diff --git a/route_link.c b/route_link.c index 3efb0490..405333bb 100644 --- a/route_link.c +++ b/route_link.c @@ -619,7 +619,7 @@ static int send_neighbour_link(struct neighbour *n) if (n->subscriber->reachable & REACHABLE_DIRECT && (!(n->subscriber->reachable&REACHABLE_ASSUMED))){ frame->destination_resolved = 1; frame->interface = n->subscriber->interface; - frame->recvaddr = frame->interface->broadcast_address; + frame->recvaddr = frame->interface->destination.address; frame->resend=-1; } ob_limitsize(frame->payload, 400); @@ -641,7 +641,7 @@ static int send_neighbour_link(struct neighbour *n) n->last_update = now; } - n->next_neighbour_update = n->last_update + n->best_link->interface->tick_ms; + n->next_neighbour_update = n->last_update + n->best_link->interface->destination.tick_ms; n->ack_counter = ACK_WINDOW; OUT(); return 0; @@ -873,7 +873,7 @@ int link_received_packet(struct subscriber *subscriber, struct overlay_interface if (neighbour->next_neighbour_update > now + 10); neighbour->next_neighbour_update = now + 10; } - link->link_timeout = now + (interface->tick_ms *5); + link->link_timeout = now + (interface->destination.tick_ms *5); // force an update soon when we need to promptly ack packets if (neighbour->using_us > now && neighbour->ack_counter <=0){ @@ -1013,7 +1013,7 @@ int link_receive(overlay_mdp_frame *mdp) version++; } - neighbour->neighbour_link_timeout = now + interface->tick_ms * 5; + neighbour->neighbour_link_timeout = now + interface->destination.tick_ms * 5; if (drop_rate != link->drop_rate || transmitter != link->transmitter) version++; @@ -1118,10 +1118,10 @@ int link_state_legacy_ack(struct overlay_frame *frame, time_ms_t now) // track the incoming link so we remember to send broadcasts struct neighbour_link *nl = get_neighbour_link(neighbour, frame->interface, iface, 0); - nl->link_timeout = now + (frame->interface->tick_ms *5); + nl->link_timeout = now + (frame->interface->destination.tick_ms *5); neighbour->legacy_protocol = 1; - neighbour->neighbour_link_timeout = now + link->interface->tick_ms * 5; + neighbour->neighbour_link_timeout = now + link->interface->destination.tick_ms * 5; if (changed){ route_version++; diff --git a/serval.h b/serval.h index 0726eca9..047ab223 100644 --- a/serval.h +++ b/serval.h @@ -381,6 +381,45 @@ struct slip_decode_state{ int dst_offset; }; +struct overlay_interface; + +struct network_destination { + struct overlay_interface *interface; + /* Number of milli-seconds per tick for this interface, which is basically related to the + the typical TX range divided by the maximum expected speed of nodes in the network. + This means that short-range communications has a higher bandwidth requirement than + long-range communications because the tick interval has to be shorter to still allow + fast-convergence time to allow for mobility. + + For wifi (nominal range 100m) it is usually 500ms. + For ~100K ISM915MHz (nominal range 1000m) it will probably be about 5000ms. + For ~10K ISM915MHz (nominal range ~3000m) it will probably be about 15000ms. + These figures will be refined over time, and we will allow people to set them per-interface. + */ + unsigned tick_ms; /* milliseconds per tick */ + + // do we aggregate packets, or send one at a time + int encapsulation; + + // time last packet was sent + time_ms_t last_tx; + + // sequence number of last packet sent to this destination. + // Used to allow NACKs that can request retransmission of recent packets. + int sequence_number; + + // rate limit for outgoing packets + struct limit_state transfer_limit; + + /* Not necessarily the real MTU, but the largest frame size we are willing to TX. + For radio links the actual maximum and the maximum that is likely to be delivered reliably are + potentially two quite different values. */ + int mtu; + + // The IPv4 destination address, for an interface this will be the broadcast address. + struct sockaddr_in address; +}; + typedef struct overlay_interface { struct sched_ent alarm; @@ -398,7 +437,6 @@ typedef struct overlay_interface { int port; int type; int socket_type; - int encapsulation; char send_broadcasts; char prefer_unicast; // can we use this interface for routes to addresses in other subnets? @@ -411,47 +449,15 @@ typedef struct overlay_interface { char point_to_point; struct subscriber *other_device; - /* Number of milli-seconds per tick for this interface, which is basically related to the - the typical TX range divided by the maximum expected speed of nodes in the network. - This means that short-range communications has a higher bandwidth requirement than - long-range communications because the tick interval has to be shorter to still allow - fast-convergence time to allow for mobility. - - For wifi (nominal range 100m) it is usually 500ms. - For ~100K ISM915MHz (nominal range 1000m) it will probably be about 5000ms. - For ~10K ISM915MHz (nominal range ~3000m) it will probably be about 15000ms. - These figures will be refined over time, and we will allow people to set them per-interface. - */ - unsigned tick_ms; /* milliseconds per tick */ unsigned int uartbps; // set serial port speed (which might be different from link speed) int ctsrts; // enabled hardware flow control if non-zero - // time last packet was sent on this interface - time_ms_t last_tx; + struct network_destination destination; - struct subscriber *next_advert; - - /* sequence number of last packet sent on this interface. - Used to allow NACKs that can request retransmission of recent packets. - */ - int sequence_number; - /* XXX need recent packet buffers to support the above */ - - struct limit_state transfer_limit; - - /* We need to make sure that interface name and broadcast address is unique for all interfaces that are UP. - We bind a separate socket per interface / broadcast address Broadcast address and netmask, if known - We really only case about distinct broadcast addresses on interfaces. - Also simplifies aliases on interfaces. */ + // the actual address of the interface. struct sockaddr_in address; - struct sockaddr_in broadcast_address; struct in_addr netmask; - /* Not necessarily the real MTU, but the largest frame size we are willing to TX on this interface. - For radio links the actual maximum and the maximum that is likely to be delivered reliably are - potentially two quite different values. */ - int mtu; - /* Use one of the INTERFACE_STATE_* constants to indicate the state of this interface. If the interface stops working or disappears, it will be marked as DOWN and the socket closed. But if it comes back up again, we should try to reuse this structure, even if the broadcast address has changed.