protocol MpegAudioVideoAdaptation -- mpeg packet format is |udp|ver|seqno|p_type|frame|payload len|payload -- This policy is designed for astero1.mpg with 400Kbps bandwidth requirement -- frame pattern is IBBPBBPBBPBBPBB initstate { -- map (movie index + interface) to drop information dropped_info hash_table interface_table = mkTable(25); -- map a movie IP address to an index movie_data hash_table movie_table = mkTable(25); } typedef struct { ip ipheader; udp udpheader; int ver; int seq_no; int pictype; int frame_no; int payload_len; blob payload; } packet; typedef struct { ip ipheader; tcp tcpheader; host movie_address; blob payload; } control; typedef struct { int index; int P_threshold; int B_threshold; } movie_data; typedef struct { int frame_type; int frame_no; } dropped_info; int I_frame = 1; int P_frame = 2; int B_frame = 3; void update_table(int i, int pictype, int frame_no) { insert(interface_table, hashKey(i), new(dropped_info,pictype,frame_no)); } int available_bandwidth(interface i) { return 2000000 - InterfaceLoad(i); } void B_forward(int threshold, int index, interface i, packet p) { try { dropped_info dropped = find(interface_table, hashKey(index)); bool undecodable = ((dropped->frame_type == P_frame) || (dropped->frame_no == p->frame_no)); if (!undecodable) { if (available_bandwidth(i) < threshold) update_table(index,B_frame,p->frame_no); else OnNeighbor(network, i, p); } } handle NoEntry => {} -- no client for this movie at the interface } void P_forward(int threshold, int index, interface i, packet p) { try { dropped_info dropped = find(interface_table, hashKey(index)); bool undecodable = (dropped->frame_type == P_frame); if (!undecodable) { if (available_bandwidth(i) < threshold) update_table(index,P_frame,p->frame_no); else OnNeighbor(network, i, p); } } handle NoEntry => {} -- no client for this movie at the interface } void I_forward(int index, interface i, packet p) { try { find(interface_table, hashKey(index)); update_table(index,0,0); OnNeighbor(network, i, p); } handle NoEntry => {} } -- We would like a hash table that -- maps a tuple of a movie and an interface to dropped information. -- But a hash key can't be a tuple. So we convert the movie address to -- an integer that is a multiple of 10, convert the interface to a number -- (hoping that getInterfaces() always returns the interfaces in the same -- order and that there are fewer than 10 of them) and then add the -- movie number to the interface number to get an index. void adaptiveForward (movie_data m, packet p) { int index = m->index; for (interface i in getInterfaces()) { if (i!= thisInterface()) { if (p->pictype == B_frame) B_forward(m->B_threshold,index,i,p); else if (p->pictype == P_frame) P_forward(m->P_threshold,index,i,p); else I_forward(index,i,p); } index = index + 1; } } -- int^5 are defined as {ver, seqno, frame_type, frame, size} stream network(packet p) { try { movie_data m = find(movie_table,hashkey(ipDst(p->ipheader))); adaptiveForward(m,p); } handle NoEntry => OnRemote(network, p); return 1; } -- P_threshold and B_threshold should be calculated from the bandwidth -- requirement typedef struct { int add_delete; int P_threshold; int B_threshold; blob payload; } movie_control_data; int Add = 0; int Delete = 1; int interfaceToInt(interface x) { int i_index = 0; int res = 0; for (interface i in getInterfaces()) { if (x == i) res = i_index; i_index = i_index + 1; } return res; } -- the following addresses reflect the astero2 data -- 225.3.2.1: multicast address of the movie -- 147.210.18.1: address of the server -- 172.17.1.1: address of the router -- below 225.3.2.1 should be p->movie_address, to be more realistic stream network(control p) { initstate { -- the maximum index allocated so far to a movie int max_movie = 0; } host dest = ipDst(p->ipheader); -- address of the server: subscription request if (dest == 147.210.18.1) { try { movie_data m = find(movie_table, hashKey(225.3.2.1)); int movie_index = m->index; -- just one client interface i = thisInterface(); int index = movie_index + interfaceToInt(i); -- if the following hash table lookup fails, we have the first -- client for the movie at this interface try find(interface_table, hashKey(index)); handle NoEntry => update_table(index,0,0); } handle NoEntry => { print("error: unknown movie: "); println(225.3.2.1); } } -- address of the router: movie add or delete request else if (dest == 172.17.1.1) { movie_control_data m = p->payload; if (m->add_delete == Delete) { try { movie_data m = find(movie_table, hashKey(225.3.2.1)); int movie_index = m->index; int i_index = 0; for (interface i in getInterfaces()) { remove(interface_table,hashKey(movie_index + i_index)); i_index = i_index + 1; } remove(movie_table, hashKey(225.3.2.1)); } handle NoEntry => {} } else { -- (m->add_delete == Add) try find(movie_table, hashKey(225.3.2.1)); handle NoEntry => { -- 100000 should be m->P_threshold -- 300000 should be m->B_threshold insert(movie_table,hashKey(225.3.2.1), new(movie_data,max_movie*10,100000,300000)); max_movie = max_movie + 1; } } } else OnRemote(network, p); return 2; }