Skip to content
Permalink
Browse files Browse the repository at this point in the history
Improve error handling of unknown gateways.
  • Loading branch information
brocaar committed Jul 9, 2020
1 parent 28daf76 commit 874fc1a
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 48 deletions.
71 changes: 29 additions & 42 deletions internal/gateway/rx_info.go
Expand Up @@ -25,68 +25,53 @@ import (
// - add the gateway location
// - set the FPGA id if available
// - decrypt the fine-timestamp (if available and AES key is set)
func UpdateMetaDataInRxInfoSet(ctx context.Context, db sqlx.Queryer, rxInfo []*gw.UplinkRXInfo) error {
for i := range rxInfo {
id := helpers.GetGatewayID(rxInfo[i])
func UpdateMetaDataInRxInfoSet(ctx context.Context, db sqlx.Queryer, rxInfoSet []*gw.UplinkRXInfo) []*gw.UplinkRXInfo {
var out []*gw.UplinkRXInfo

for i := range rxInfoSet {
rxInfo := rxInfoSet[i]

id := helpers.GetGatewayID(rxInfo)
g, err := storage.GetAndCacheGateway(ctx, db, id)
if err != nil {
log.WithFields(log.Fields{
"ctx_id": ctx.Value(logging.ContextIDKey),
"gateway_id": id,
}).WithError(err).Error("get gateway error")
if errors.Cause(err) == storage.ErrDoesNotExist {
log.WithFields(log.Fields{
"ctx_id": ctx.Value(logging.ContextIDKey),
"gateway_id": id,
}).Warning("uplink received by unknown gateway")
} else {
log.WithFields(log.Fields{
"ctx_id": ctx.Value(logging.ContextIDKey),
"gateway_id": id,
}).WithError(err).Error("get gateway error")
}
continue
}

// set gateway location
rxInfo[i].Location = &common.Location{
rxInfo.Location = &common.Location{
Latitude: g.Location.Latitude,
Longitude: g.Location.Longitude,
Altitude: g.Altitude,
}

var board storage.GatewayBoard
if int(rxInfo[i].Board) < len(g.Boards) {
board = g.Boards[int(rxInfo[i].Board)]
if int(rxInfo.Board) < len(g.Boards) {
board = g.Boards[int(rxInfo.Board)]
}

// set FPGA ID
// this is useful when the AES decryption key is not set as it
// indicates which key to use for decryption
if rxInfo[i].FineTimestampType == gw.FineTimestampType_ENCRYPTED && board.FPGAID != nil {
tsInfo := rxInfo[i].GetEncryptedFineTimestamp()
if tsInfo == nil {
log.WithFields(log.Fields{
"ctx_id": ctx.Value(logging.ContextIDKey),
"gateway_id": id,
}).Error("encrypted_fine_timestamp must not be nil")
continue
}

if tsInfo := rxInfo.GetEncryptedFineTimestamp(); tsInfo != nil && board.FPGAID != nil {
if len(tsInfo.FpgaId) == 0 {
tsInfo.FpgaId = board.FPGAID[:]
}
}

// decrypt fine-timestamp when the AES key is known
if rxInfo[i].FineTimestampType == gw.FineTimestampType_ENCRYPTED && board.FineTimestampKey != nil {
tsInfo := rxInfo[i].GetEncryptedFineTimestamp()
if tsInfo == nil {
log.WithFields(log.Fields{
"ctx_id": ctx.Value(logging.ContextIDKey),
"gateway_id": id,
}).Error("encrypted_fine_timestamp must not be nil")
continue
}

if rxInfo[i].Time == nil {
log.WithFields(log.Fields{
"ctx_id": ctx.Value(logging.ContextIDKey),
"gateway_id": id,
}).Error("time must not be nil")
continue
}

rxTime, err := ptypes.Timestamp(rxInfo[i].Time)
if tsInfo := rxInfo.GetEncryptedFineTimestamp(); tsInfo != nil && board.FineTimestampKey != nil {
rxTime, err := ptypes.Timestamp(rxInfo.GetTime())
if err != nil {
log.WithFields(log.Fields{
"ctx_id": ctx.Value(logging.ContextIDKey),
Expand All @@ -103,14 +88,16 @@ func UpdateMetaDataInRxInfoSet(ctx context.Context, db sqlx.Queryer, rxInfo []*g
continue
}

rxInfo[i].FineTimestampType = gw.FineTimestampType_PLAIN
rxInfo[i].FineTimestamp = &gw.UplinkRXInfo_PlainFineTimestamp{
rxInfo.FineTimestampType = gw.FineTimestampType_PLAIN
rxInfo.FineTimestamp = &gw.UplinkRXInfo_PlainFineTimestamp{
PlainFineTimestamp: &plainTS,
}
}

out = append(out, rxInfo)
}

return nil
return out
}

func decryptFineTimestamp(key lorawan.AES128Key, rxTime time.Time, ts gw.EncryptedFineTimestamp) (gw.PlainFineTimestamp, error) {
Expand Down
15 changes: 14 additions & 1 deletion internal/gateway/stats/stats.go
Expand Up @@ -18,6 +18,8 @@ import (
loraband "github.com/brocaar/lorawan/band"
)

var ErrAbort = errors.New("abort")

type statsContext struct {
ctx context.Context
gateway storage.Gateway
Expand All @@ -40,6 +42,9 @@ func Handle(ctx context.Context, stats gw.GatewayStats) error {

for _, t := range tasks {
if err := t(&sctx); err != nil {
if err == ErrAbort {
return nil
}
return err
}
}
Expand All @@ -51,7 +56,15 @@ func getGateway(ctx *statsContext) error {
gatewayID := helpers.GetGatewayID(&ctx.gatewayStats)
gw, err := storage.GetAndCacheGateway(ctx.ctx, storage.DB(), gatewayID)
if err != nil {
return errors.Wrap(err, "get gateway error")
if errors.Cause(err) == storage.ErrDoesNotExist {
log.WithFields(log.Fields{
"ctx_id": ctx.ctx.Value(logging.ContextIDKey),
"gateway_id": gatewayID,
}).Warning("gateway/stats: stats received by unknown gateway")
return ErrAbort
} else {
return errors.Wrap(err, "get gateway error")
}
}

ctx.gateway = gw
Expand Down
13 changes: 8 additions & 5 deletions internal/uplink/uplink.go
Expand Up @@ -178,6 +178,14 @@ func collectUplinkFrames(ctx context.Context, uplinkFrame gw.UplinkFrame) error
}

func handleCollectedUplink(ctx context.Context, uplinkFrame gw.UplinkFrame, rxPacket models.RXPacket) error {
// update the gateway meta-data
rxPacket.RXInfoSet = gateway.UpdateMetaDataInRxInfoSet(ctx, storage.DB(), rxPacket.RXInfoSet)

// Return if the RXInfoSet is empty.
if len(rxPacket.RXInfoSet) == 0 {
return nil
}

var uplinkIDs []uuid.UUID
for _, p := range rxPacket.RXInfoSet {
uplinkIDs = append(uplinkIDs, helpers.GetUplinkID(p))
Expand All @@ -189,11 +197,6 @@ func handleCollectedUplink(ctx context.Context, uplinkFrame gw.UplinkFrame, rxPa
"ctx_id": ctx.Value(logging.ContextIDKey),
}).Info("uplink: frame(s) collected")

// update the gateway meta-data
if err := gateway.UpdateMetaDataInRxInfoSet(ctx, storage.DB(), rxPacket.RXInfoSet); err != nil {
log.WithError(err).Error("uplink: update gateway meta-data in rx-info set error")
}

// log the frame for each receiving gateway.
if err := framelog.LogUplinkFrameForGateways(ctx, ns.UplinkFrameLog{
PhyPayload: uplinkFrame.PhyPayload,
Expand Down

0 comments on commit 874fc1a

Please sign in to comment.