protected AHHeader(short hops, AHHeader head) { //Set a new number of hops: Hops = hops; //Copy the rest: Ttl = head.Ttl; Opts = head.Opts; _src = head._src; _dest = head._dest; _data = head._data; }
public void Send(ICopyable data) { /* * Assemble an AHPacket: */ if( _header == null ) { AHHeader ahh = new AHHeader(_hops, _ttl, _source, _dest, _options); _header = MemBlock.Copy(new CopyList( PType.Protocol.AH, ahh)); _header_length = _header.Length; } byte[] ah_packet; int packet_length; int packet_offset; //Try to get the shared BufferAllocator, useful when //we don't know how big the data is, which in general //is just as expensive as doing a CopyTo... BufferAllocator ba = Interlocked.Exchange<BufferAllocator>(ref _buf_alloc, null); if( ba != null ) { try { ah_packet = ba.Buffer; packet_offset = ba.Offset; int tmp_off = packet_offset; tmp_off += _header.CopyTo(ah_packet, packet_offset); tmp_off += data.CopyTo(ah_packet, tmp_off); packet_length = tmp_off - packet_offset; ba.AdvanceBuffer(packet_length); } catch(System.Exception x) { throw new SendException(false, "could not write the packet, is it too big?", x); } finally { //Put the BA back Interlocked.Exchange<BufferAllocator>(ref _buf_alloc, ba); } } else { //Oh well, someone else is using the buffer, just go ahead //and allocate new memory: packet_offset = 0; packet_length = _header_length + data.Length; ah_packet = new byte[ packet_length ]; int off_to_data = _header.CopyTo(ah_packet, 0); data.CopyTo(ah_packet, off_to_data); } MemBlock mb_packet = MemBlock.Reference(ah_packet, packet_offset, packet_length); /* * Now we announce this packet, the AHHandler will * handle routing it for us */ _n.HandleData(mb_packet, _from, this); }
/** * Here we handle routing AHPackets */ public void HandleData(MemBlock data, ISender ret_path, object st) { AHState state = _state; //Read the state, it can't change after the read var header = new AHHeader(data); var payload = data.Slice(header.Length); Connection next_con; //Check to see if we can use a Leaf connection: int dest_idx = state.Leafs.IndexOf(header.Destination); if( dest_idx >= 0 ) { next_con = state.Leafs[dest_idx]; } else { var alg = state.GetRoutingAlgo(header); Pair<Connection, bool> result = alg.NextConnection(ret_path as Edge, header); if( result.Second ) { //Send a response exactly back to the node that sent to us var resp_send = new AHSender(_n, ret_path, header.Source, _n.DefaultTTLFor(header.Source), AHHeader.Options.Exact); _n.HandleData( payload, resp_send, this); } next_con = result.First; } //Send it on: if( next_con != null ) { //Now we do the sending: var new_packet = new CopyList(PType.Protocol.AH, header.IncrementHops(), payload); try { next_con.Edge.Send(new_packet); } catch(EdgeException) { //Just drop the packet... } } }
public AHRoutingAlgorithm GetRoutingAlgo(AHHeader head) { int addclass = head.Destination.Class; if( addclass == AHAddress.ClassValue ) { ushort opts = head.Opts; if( opts == AHHeader.Options.Last || opts == AHHeader.Options.Greedy ) { return _greedy; } else { return _annealing; } } else if( addclass == DirectionalAddress.ClassValue ) { return _directional; } else { throw new Exception( String.Format("No router for class: {0}", addclass)); } }
public override Pair<Connection, bool> NextConnection(Edge from, AHHeader h) { DirectionalAddress dest = (DirectionalAddress)h.Destination; if( h.Ttl <= h.Hops ) { //Deliver it to us but stop it here: return _NULL_TRUE; } if ( dest.Bearing == DirectionalAddress.Direction.Left ) { if( h.Opts == AHHeader.Options.Path ) { return _LEFT_TRUE; } else { return _LEFT_FALSE; } } else if (dest.Bearing == DirectionalAddress.Direction.Right) { if( h.Opts == AHHeader.Options.Path ) { return _RIGHT_TRUE; } else { return _RIGHT_FALSE; } } else { throw new System.Exception( System.String.Format("Unrecognized direction: {0}", dest.Bearing)); } }
public override Pair<Connection, bool> NextConnection(Edge from, AHHeader head) { Address dest = head.Destination; int d_idx = _structs.IndexOf(dest); if( d_idx >= 0 ) { //We have a direct connection: Connection next = _structs[d_idx]; if( next != _local_con ) { return new Pair<Connection,bool>(next, false); } else { return new Pair<Connection, bool>(null, true); } } else { var ah_dest = (AHAddress)dest; int left_idx = ~d_idx; Connection l_c = _structs[left_idx]; int right_idx = left_idx - 1; Connection r_c = _structs[right_idx]; Connection next_con; Connection other_con; if( ah_dest.IsCloserToFirst((AHAddress)l_c.Address, (AHAddress)r_c.Address) ) { next_con = l_c; other_con = r_c; } else { next_con = r_c; other_con = l_c; } //See if we need to get it: /* everyone gets "path" packets, * if it's exact, only the destination gets it, handled above * otherwise, only the two nodes on either side of the destination get * it */ bool local = head.Opts == AHHeader.Options.Path || ((next_con == _local_con || other_con == _local_con) && head.Opts != AHHeader.Options.Exact); Connection to_send; //Check not to send it back the way it came: if(from == null) { /* * This packet is from us, so just send it to the closest * node, other than us. */ to_send = _local_con != next_con ? next_con : other_con; } else if(next_con.Edge == from) { //Don't send it back the way it came: to_send = other_con; } else { //Great, the closest has not yet been visited: to_send = next_con; } //Now, make sure not to send it to ourselves: to_send = to_send == _local_con ? null : to_send; return new Pair<Connection, bool>(to_send, local); } }
public override Pair<Connection, bool> NextConnection(Edge from, AHHeader head) { Address dest = head.Destination; int d_idx = _structs.IndexOf(dest); Connection next_con; if( d_idx >= 0 ) { //We have a direct connection: next_con = _structs[d_idx]; } else { //We have to check the right and the left: var ah_dest = (AHAddress)dest; int left_idx = ~d_idx; Connection l_c = _structs[left_idx]; int right_idx = left_idx - 1; Connection r_c = _structs[right_idx]; if( ah_dest.IsCloserToFirst((AHAddress)l_c.Address, (AHAddress)r_c.Address) ) { next_con = l_c; } else { next_con = r_c; } /* * Note, DO NOT DO COMPARISONS WITH INDEX VALUES!!!!! * do the the wrap around, _structs[x] == _structs[y] * when x = y + k * _structs.Count for all k, so equality * of Connection is not the same as equality of index */ if( head.Hops >= head.Ttl ) { //Only deliver if we are the closest or last mode: bool local = next_con == _local_con || head.Opts == AHHeader.Options.Last; if( local ) { return _LOCAL; } else { return _NO_ONE; } } } return next_con == _local_con ? _LOCAL : new Pair<Connection, bool>(next_con, false); }
/** compute the next step in the route * @param from the Edge the packet came in on * @param head the header to route * @return next connection and bool indicating if local node should get * packet. If there is no next connection, the connection will be null */ public abstract Pair<Connection, bool> NextConnection(Edge from, AHHeader head);