mirror of
				https://gitea.osmocom.org/cellular-infrastructure/osmo-ggsn.git
				synced 2025-11-04 06:03:23 +00:00 
			
		
		
		
	WIP: add gtp_3way_resp(): unclear if we really need this
Change-Id: Ifb7e7465f5c8a6e1ee0cff74028bf7b4737e9989
This commit is contained in:
		
							
								
								
									
										66
									
								
								gtp/gtp.c
									
									
									
									
									
								
							
							
						
						
									
										66
									
								
								gtp/gtp.c
									
									
									
									
									
								
							@@ -503,6 +503,72 @@ static int gtp_conf(struct gsn_t *gsn, uint8_t version, struct sockaddr_in *peer
 | 
				
			|||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Respond, to a request, but expect the other side to.
 | 
				
			||||||
 | 
					 * E.g. Send a SGSN Context Request */
 | 
				
			||||||
 | 
					static int gtp_3way_resp(struct gsn_t *gsn, union gtp_packet *packet, int len,
 | 
				
			||||||
 | 
								 struct sockaddr_in *peer, int fd,
 | 
				
			||||||
 | 
								 uint16_t seq, uint64_t tid, uint16_t flow, uint32_t tei,
 | 
				
			||||||
 | 
								 const struct in_addr *inetaddr, void *cbp)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
 | 
				
			||||||
 | 
						struct qmsg_t *qmsg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ver == 0) {	/* Version 0 */
 | 
				
			||||||
 | 
							packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
 | 
				
			||||||
 | 
							packet->gtp0.h.seq = hton16(seq);
 | 
				
			||||||
 | 
							packet->gtp0.h.tid = htobe64(tid);
 | 
				
			||||||
 | 
							packet->gtp0.h.flow = hton16(flow);
 | 
				
			||||||
 | 
						} else if (ver == 1 && (packet->flags & GTP1HDR_F_SEQ)) {	/* Version 1 with seq */
 | 
				
			||||||
 | 
							packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
 | 
				
			||||||
 | 
							packet->gtp1l.h.seq = hton16(seq);
 | 
				
			||||||
 | 
							packet->gtp1l.h.tei = hton32(tei);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (fcntl(fd, F_SETFL, 0)) {
 | 
				
			||||||
 | 
							LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (sendto(fd, packet, len, 0,
 | 
				
			||||||
 | 
							   (const struct sockaddr *)peer, sizeof(struct sockaddr_in)) < 0) {
 | 
				
			||||||
 | 
							rate_ctr_inc2(gsn->ctrg, GSN_CTR_ERR_SENDTO);
 | 
				
			||||||
 | 
							LOGP(DLGTP, LOGL_ERROR,
 | 
				
			||||||
 | 
							     "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
 | 
				
			||||||
 | 
							     (unsigned long)&packet, len, strerror(errno));
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Use new queue structure */
 | 
				
			||||||
 | 
						if (queue_newmsg(gsn->queue_resp, &qmsg, peer, seq)) {
 | 
				
			||||||
 | 
							rate_ctr_inc2(gsn->ctrg, GSN_CTR_ERR_QUEUEFULL);
 | 
				
			||||||
 | 
							LOGP(DLGTP, LOGL_ERROR, "Retransmit resp queue is full (seq=%" PRIu16 ")\n",
 | 
				
			||||||
 | 
							     seq);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							unsigned int t3_hold_resp;
 | 
				
			||||||
 | 
							LOGP(DLGTP, LOGL_DEBUG, "Registering seq=%" PRIu16
 | 
				
			||||||
 | 
										" in restransmit resp queue\n", seq);
 | 
				
			||||||
 | 
							t3_hold_resp = osmo_tdef_get(gsn->tdef, GTP_GSN_TIMER_T3_HOLD_RESPONSE, OSMO_TDEF_S, -1);
 | 
				
			||||||
 | 
							memcpy(&qmsg->p, packet, sizeof(union gtp_packet));
 | 
				
			||||||
 | 
							qmsg->l = len;
 | 
				
			||||||
 | 
							qmsg->timeout = time(NULL) + t3_hold_resp; /* When to timeout */
 | 
				
			||||||
 | 
							qmsg->retrans = 0;	/* No retransmissions so far */
 | 
				
			||||||
 | 
							qmsg->cbp = cbp;
 | 
				
			||||||
 | 
							qmsg->type = 0;
 | 
				
			||||||
 | 
							qmsg->fd = fd;
 | 
				
			||||||
 | 
							/* No need to add to pdp list here, because even on pdp ctx free
 | 
				
			||||||
 | 
							   we want to leave messages in queue_resp until timeout to
 | 
				
			||||||
 | 
							   detect duplicates */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* Rearm timer: Retrans time for qmsg just queued may be required
 | 
				
			||||||
 | 
							   before an existing one (for instance a gtp echo req) */
 | 
				
			||||||
 | 
							gtp_queue_timer_start(gsn);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Send a GTP Response (generic call) */
 | 
					/* Send a GTP Response (generic call) */
 | 
				
			||||||
static int gtp_resp(struct gsn_t *gsn, union gtp_packet *packet, int len, struct sockaddr_in *peer, int fd,
 | 
					static int gtp_resp(struct gsn_t *gsn, union gtp_packet *packet, int len, struct sockaddr_in *peer, int fd,
 | 
				
			||||||
		     uint16_t seq, uint64_t tid, uint16_t flow, uint32_t teidc)
 | 
							     uint16_t seq, uint64_t tid, uint16_t flow, uint32_t teidc)
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user