📄 rfc2507c.cc
字号:
/* * rfc2507c.{cc,hh} -- element compresses IP headers a la RFC 2507 * Robert Morris * * Copyright (c) 1999-2000 Massachusetts Institute of Technology * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, subject to the conditions * listed in the Click LICENSE file. These conditions include: you must * preserve this copyright notice, and you cannot mention the copyright * holders in advertising related to the Software without their permission. * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This * notice is a summary of the Click LICENSE file; the license in that file is * legally binding. */#include <click/config.h>#include "rfc2507c.hh"CLICK_DECLSRFC2507c::RFC2507c(){ add_input(); add_output();}RFC2507c::~RFC2507c(){}inlineRFC2507c::tcpip::operator IPFlowID() const{ return IPFlowID(_ip.ip_src, _tcp.th_sport, _ip.ip_dst, _tcp.th_dport);}/* * Make a packet containing an uncompressed and uncompressible * packet, not to be associated with a CID. */WritablePacket *RFC2507c::make_other(Packet *p){ WritablePacket *q = Packet::make(p->length() + 1); q->data()[0] = PT_OTHER; memcpy(q->data() + 1, p->data(), p->length()); return q;}/* * Make a packet containing an uncompressed tcp/ip packet, * and also indicating a CID. The point is to cause the * decompressor to sync context with us. */WritablePacket *RFC2507c::make_full(int cid, Packet *p){ WritablePacket *q = Packet::make(p->length() + 2); q->data()[0] = PT_FULL_HEADER; q->data()[1] = cid; memcpy(q->data() + 2, p->data(), p->length()); return(q);}/* * Encode the difference between two fields (eg TCP seq #) in 0, * 1, or 2 bytes. If it won't fit in 2, return -1 signifying * that a full packet should be sent. If there is no difference, * return 0. If there is a difference, return 1. */intRFC2507c::encode16(int o, int n, char *p, int &i){ return(encodeX(ntohs(o), ntohs(n), p, i));}intRFC2507c::encode32(int o, int n, char *p, int &i){ return(encodeX(ntohl(o), ntohl(n), p, i));}intRFC2507c::encodeX(int o, int n, char *p, int &i){ if(o == n) return(0); if(n < o) return(-1); if(n - o < 256){ p[i++] = n - o; return(1); } if(n - o < 65536){ p[i++] = 0; p[i++] = (n - o) >> 8; p[i++] = n - o; return(1); } return(-1);}Packet *RFC2507c::make_compressed(int cid, Packet *p){ int flags = 0; /* ROIPSAWU */ int flen = 0; char fbuf[512]; /* encode into this buf[flen] */ const click_ip *ipp = p->ip_header(); const click_tcp *tcpp = p->tcp_header(); int x; struct tcpip *ctx = &_ccbs[cid]._context; if(ipp->ip_v != ctx->_ip.ip_v || ipp->ip_hl != ctx->_ip.ip_hl || ipp->ip_tos != ctx->_ip.ip_tos || (ipp->ip_off & htons(IP_DF)) != (ctx->_ip.ip_off & htons(IP_DF)) || ipp->ip_ttl != ctx->_ip.ip_ttl || tcpp->th_off != ctx->_tcp.th_off){ click_chatter("full1"); return make_full(cid, p); } x = encode16(ctx->_tcp.th_urp, tcpp->th_urp, fbuf, flen); if(x < 0){ click_chatter("full urp"); return make_full(cid, p); } if(x) flags |= 1; x = encode16(ctx->_tcp.th_win, tcpp->th_win, fbuf, flen); if(x < 0){ click_chatter("full win"); return make_full(cid, p); } if(x) flags |= (1 << 1); x = encode32(ctx->_tcp.th_ack, tcpp->th_ack, fbuf, flen); if(x < 0){ click_chatter("full ack"); return make_full(cid, p); } if(x) flags |= (1 << 2); x = encode32(ctx->_tcp.th_seq, tcpp->th_seq, fbuf, flen); if(x < 0){ click_chatter("full seq"); return make_full(cid, p); } if(x) flags |= (1 << 3); if(ntohs(ipp->ip_id) != ntohs(ctx->_ip.ip_id) + 1){ x = encode16(ctx->_ip.ip_id, ipp->ip_id, fbuf, flen); if(x < 0){ click_chatter("full id"); return make_full(cid, p); } if(x) flags |= (1 << 5); } if(tcpp->th_flags & TH_PUSH) flags |= (1 << 4); WritablePacket *q = Packet::make(p->length() - sizeof(click_ip) - sizeof(struct click_tcp) + 5 + flen); q->data()[0] = PT_COMPRESSED_TCP; q->data()[1] = cid; q->data()[2] = flags; memcpy(q->data() + 3, &tcpp->th_sum, 2); memcpy(q->data() + 5, fbuf, flen); memcpy(q->data() + 5 + flen, p->data() + sizeof(click_ip) + sizeof(struct click_tcp), p->length() - sizeof(click_ip) - sizeof(struct click_tcp)); return(q);}/* * Zero out fields that should not participate in * identifying a flow. */voidRFC2507c::make_key(const struct tcpip &from, struct tcpip &to){ to = from; to._ip.ip_tos = 0; to._ip.ip_id = 0; to._ip.ip_len = 0; to._ip.ip_off = 0; to._ip.ip_ttl = 0; to._ip.ip_sum = 0; to._tcp.th_seq = 0; to._tcp.th_ack = 0; to._tcp.th_flags2 = 0; to._tcp.th_off = 0; to._tcp.th_flags = 0; to._tcp.th_win = 0; to._tcp.th_sum = 0; to._tcp.th_urp = 0;}Packet *RFC2507c::simple_action(Packet *p){ const click_ip *ipp = p->ip_header(); assert(ipp && p->ip_header_offset() == 0); const click_tcp *tcpp = p->tcp_header(); int cid; Packet *q = 0; if(ipp->ip_hl != 5 || ipp->ip_v != 4 || (ipp->ip_off & htons(IP_OFFMASK | IP_MF)) != 0 || ipp->ip_p != IPPROTO_TCP || (tcpp->th_flags & (TH_FIN|TH_SYN|TH_RST|TH_ACK)) != TH_ACK){ /* cannot compress this packet */ click_chatter("cannot compress packet"); q = make_other(p); } else { IPFlowID key(p); struct tcpip ti; ti._ip = *ipp; ti._tcp = *tcpp; if(_map.findp(key) && (cid = _map[key])){ q = make_compressed(cid, p); _ccbs[cid]._context = ti; } else { /* pick a CID to re-use */ cid = (random() % (TCP_SPACE-1)) + 1; /* delete the old key */ IPFlowID okey(_ccbs[cid]._context); if(_map.findp(okey) && _map[okey]){ _map.insert(okey, 0); } _map.insert(key, cid); click_chatter("sport %d dport %d added cid %d", ntohs(key.sport()), ntohs(key.dport()), cid); q = make_full(cid, p); _ccbs[cid]._context = ti; } } p->kill(); return(q);}EXPORT_ELEMENT(RFC2507c) #include <click/hashmap.cc>#if EXPLICIT_TEMPLATE_INSTANCEStemplate class HashMap<IPFlowID, int>;#endifCLICK_ENDDECLS
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -