drivers/net/slip/slhc.c

Source file repositories/reference/linux-study-clean/drivers/net/slip/slhc.c

File Facts

System
Linux kernel
Corpus path
drivers/net/slip/slhc.c
Extension
.c
Size
20064 bytes
Lines
781
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if(deltaS == ntohs(cs->cs_ip.tot_len) - hlen){
			/* special case for data xfer */
			changes = SPECIAL_D;
			cp = new_seq;
		}
		break;
	}
	deltaS = ntohs(ip->id) - ntohs(cs->cs_ip.id);
	if(deltaS != 1){
		cp = encode(cp,deltaS);
		changes |= NEW_I;
	}
	if(th->psh)
		changes |= TCP_PUSH_BIT;
	/* Grab the cksum before we overwrite it below.  Then update our
	 * state with this packet's header.
	 */
	csum = th->check;
	memcpy(&cs->cs_ip,ip,20);
	memcpy(&cs->cs_tcp,th,20);
	/* We want to use the original packet as our compressed packet.
	 * (cp - new_seq) is the number of bytes we need for compressed
	 * sequence numbers.  In addition we need one byte for the change
	 * mask, one for the connection id and two for the tcp checksum.
	 * So, (cp - new_seq) + 4 bytes of header are needed.
	 */
	deltaS = cp - new_seq;
	if(compress_cid == 0 || comp->xmit_current != cs->cs_this){
		cp = ocp;
		*cpp = ocp;
		*cp++ = changes | NEW_C;
		*cp++ = cs->cs_this;
		comp->xmit_current = cs->cs_this;
	} else {
		cp = ocp;
		*cpp = ocp;
		*cp++ = changes;
	}
	*(__sum16 *)cp = csum;
	cp += 2;
/* deltaS is now the size of the change section of the compressed header */
	memcpy(cp,new_seq,deltaS);	/* Write list of deltas */
	memcpy(cp+deltaS,icp+hlen,isize-hlen);
	comp->sls_o_compressed++;
	ocp[0] |= SL_TYPE_COMPRESSED_TCP;
	return isize - hlen + deltaS + (cp - ocp);

	/* Update connection state cs & send uncompressed packet (i.e.,
	 * a regular ip/tcp packet but with the 'conversation id' we hope
	 * to use on future compressed packets in the protocol field).
	 */
uncompressed:
	memcpy(&cs->cs_ip,ip,20);
	memcpy(&cs->cs_tcp,th,20);
	if (ip->ihl > 5)
	  memcpy(cs->cs_ipopt, ip+1, ((ip->ihl) - 5) * 4);
	if (th->doff > 5)
	  memcpy(cs->cs_tcpopt, th+1, ((th->doff) - 5) * 4);
	comp->xmit_current = cs->cs_this;
	comp->sls_o_uncompressed++;
	memcpy(ocp, icp, isize);
	*cpp = ocp;
	ocp[9] = cs->cs_this;
	ocp[0] |= SL_TYPE_UNCOMPRESSED_TCP;
	return isize;
}


int
slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
{
	int changes;
	long x;
	struct tcphdr *thp;
	struct iphdr *ip;
	struct cstate *cs;
	int len, hdrlen;
	unsigned char *cp = icp;
	const unsigned char *end = icp + isize;

	/* We've got a compressed packet; read the change byte */
	comp->sls_i_compressed++;
	if(isize < 3){
		comp->sls_i_error++;
		return 0;
	}
	if (!comp->rstate)
		goto bad;
	changes = *cp++;
	if(changes & NEW_C){

Annotation

Implementation Notes