Skip to content

Commit e2f12eb

Browse files
Mahmood Mohammed Seoudclaude
andcommitted
✨ feat: configurable DTP params, fix div-by-zero crash
Add dtp_mtu, dtp_throughput, dtp_timeout as configurable parameters across the full stack: config.yaml → CLI → protobuf → agent. Root cause fix: DTP_DEFAULT_THROUGHPUT was 0 ("unlimited") which caused integer division by zero in libdtp's compute_dtp_metrics(), crashing the agent with SIGFPE during every DTP download. Changes: - deploy.proto: add dtp_mtu/dtp_throughput/dtp_timeout fields (18-20) - config.py: add DTP fields to ModuleConfig with sensible defaults - csp.py: pass DTP params to DTPServer and DeployRequest - dtp_client.c: accept params with 0→default fallback - deploy_handler.c: forward proto fields to dtp_download_file Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 8b44bb2 commit e2f12eb

13 files changed

Lines changed: 173 additions & 28 deletions

File tree

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "satdeploy"
7-
version = "0.2.1"
7+
version = "0.3.0"
88
description = "Deployment tool for embedded Linux satellites — push, track, rollback over SSH and CSP"
99
readme = "README.md"
1010
license = {text = "MIT"}

satdeploy-agent/include/satdeploy_agent.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,10 +118,14 @@ int backup_list(const char *app_name, backup_list_callback callback, void *user_
118118
* @param payload_id DTP payload identifier.
119119
* @param dest_path Local path to save the downloaded file.
120120
* @param expected_size Expected file size (0 to skip size check).
121+
* @param mtu Max transmission unit (0 = use default 1024).
122+
* @param throughput Target throughput in bytes/s (0 = use default 10 MB/s).
123+
* @param timeout Transfer timeout in seconds (0 = use default 60).
121124
* @return 0 on success, -1 on failure.
122125
*/
123126
int dtp_download_file(uint32_t server_node, uint16_t payload_id,
124-
const char *dest_path, uint32_t expected_size);
127+
const char *dest_path, uint32_t expected_size,
128+
uint32_t mtu, uint32_t throughput, uint32_t timeout);
125129

126130
/**
127131
* Save app deployment metadata.

satdeploy-agent/proto/deploy.pb-c.c

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ void satdeploy__deploy_response__free_unpacked
187187
assert(message->base.descriptor == &satdeploy__deploy_response__descriptor);
188188
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
189189
}
190-
static const ProtobufCFieldDescriptor satdeploy__deploy_request__field_descriptors[17] =
190+
static const ProtobufCFieldDescriptor satdeploy__deploy_request__field_descriptors[20] =
191191
{
192192
{
193193
"command",
@@ -393,15 +393,54 @@ static const ProtobufCFieldDescriptor satdeploy__deploy_request__field_descripto
393393
0, /* flags */
394394
0,NULL,NULL /* reserved1,reserved2, etc */
395395
},
396+
{
397+
"dtp_mtu",
398+
18,
399+
PROTOBUF_C_LABEL_NONE,
400+
PROTOBUF_C_TYPE_UINT32,
401+
0, /* quantifier_offset */
402+
offsetof(Satdeploy__DeployRequest, dtp_mtu),
403+
NULL,
404+
NULL,
405+
0, /* flags */
406+
0,NULL,NULL /* reserved1,reserved2, etc */
407+
},
408+
{
409+
"dtp_throughput",
410+
19,
411+
PROTOBUF_C_LABEL_NONE,
412+
PROTOBUF_C_TYPE_UINT32,
413+
0, /* quantifier_offset */
414+
offsetof(Satdeploy__DeployRequest, dtp_throughput),
415+
NULL,
416+
NULL,
417+
0, /* flags */
418+
0,NULL,NULL /* reserved1,reserved2, etc */
419+
},
420+
{
421+
"dtp_timeout",
422+
20,
423+
PROTOBUF_C_LABEL_NONE,
424+
PROTOBUF_C_TYPE_UINT32,
425+
0, /* quantifier_offset */
426+
offsetof(Satdeploy__DeployRequest, dtp_timeout),
427+
NULL,
428+
NULL,
429+
0, /* flags */
430+
0,NULL,NULL /* reserved1,reserved2, etc */
431+
},
396432
};
397433
static const unsigned satdeploy__deploy_request__field_indices_by_name[] = {
398434
1, /* field[1] = app_name */
399435
3, /* field[3] = appsys_node */
400436
14, /* field[14] = chunk_data */
401437
12, /* field[12] = chunk_seq */
402438
0, /* field[0] = command */
439+
17, /* field[17] = dtp_mtu */
403440
6, /* field[6] = dtp_server_node */
404441
7, /* field[7] = dtp_server_port */
442+
18, /* field[18] = dtp_throughput */
443+
19, /* field[19] = dtp_timeout */
405444
10, /* field[10] = expected_checksum */
406445
9, /* field[9] = expected_size */
407446
16, /* field[16] = file_mode */
@@ -416,7 +455,7 @@ static const unsigned satdeploy__deploy_request__field_indices_by_name[] = {
416455
static const ProtobufCIntRange satdeploy__deploy_request__number_ranges[1 + 1] =
417456
{
418457
{ 1, 0 },
419-
{ 0, 17 }
458+
{ 0, 20 }
420459
};
421460
const ProtobufCMessageDescriptor satdeploy__deploy_request__descriptor =
422461
{
@@ -426,7 +465,7 @@ const ProtobufCMessageDescriptor satdeploy__deploy_request__descriptor =
426465
"Satdeploy__DeployRequest",
427466
"satdeploy",
428467
sizeof(Satdeploy__DeployRequest),
429-
17,
468+
20,
430469
satdeploy__deploy_request__field_descriptors,
431470
satdeploy__deploy_request__field_indices_by_name,
432471
1, satdeploy__deploy_request__number_ranges,

satdeploy-agent/proto/deploy.pb-c.h

Lines changed: 16 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

satdeploy-agent/proto/deploy.proto

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@ message DeployRequest {
5454

5555
// Source file permission mode (e.g., 0755, 0644). 0 = use default (0755).
5656
uint32 file_mode = 17;
57+
58+
// DTP transfer tuning (0 = use agent defaults)
59+
uint32 dtp_mtu = 18; // Max transmission unit in bytes (default: 1024)
60+
uint32 dtp_throughput = 19; // Target throughput in bytes/s (default: 10000000)
61+
uint32 dtp_timeout = 20; // Transfer timeout in seconds (default: 60)
5762
}
5863

5964
// Backup information returned by CMD_LIST_VERSIONS

satdeploy-agent/src/deploy_handler.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -705,7 +705,9 @@ static void handle_deploy(const Satdeploy__DeployRequest *req,
705705
snprintf(temp_path, sizeof(temp_path), "%s.tmp", req->remote_path);
706706

707707
if (dtp_download_file(req->dtp_server_node, req->payload_id,
708-
temp_path, req->expected_size) != 0) {
708+
temp_path, req->expected_size,
709+
req->dtp_mtu, req->dtp_throughput,
710+
req->dtp_timeout) != 0) {
709711
resp->success = 0;
710712
resp->error_code = SATDEPLOY__DEPLOY_ERROR__ERR_DTP_DOWNLOAD_FAILED;
711713
resp->error_message = "DTP download failed";

satdeploy-agent/src/dtp_client.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
/* DTP configuration defaults */
2020
#define DTP_DEFAULT_TIMEOUT_S 60
2121
#define DTP_DEFAULT_MTU 1024
22-
#define DTP_DEFAULT_THROUGHPUT 0 /* 0 = unlimited */
22+
#define DTP_DEFAULT_THROUGHPUT 10000000 /* bytes/s — must be non-zero to avoid div-by-zero in compute_dtp_metrics */
2323

2424
/* Context for file download */
2525
typedef struct {
@@ -99,11 +99,16 @@ static void on_download_release(dtp_t *session) {
9999
}
100100

101101
int dtp_download_file(uint32_t server_node, uint16_t payload_id,
102-
const char *dest_path, uint32_t expected_size) {
102+
const char *dest_path, uint32_t expected_size,
103+
uint32_t mtu, uint32_t throughput, uint32_t timeout) {
103104
if (dest_path == NULL) {
104105
return -1;
105106
}
106107

108+
/* Apply defaults for zero values */
109+
if (mtu == 0) mtu = DTP_DEFAULT_MTU;
110+
if (throughput == 0) throughput = DTP_DEFAULT_THROUGHPUT;
111+
if (timeout == 0) timeout = DTP_DEFAULT_TIMEOUT_S;
107112

108113
/* Open destination file */
109114
FILE *fp = fopen(dest_path, "wb");
@@ -130,11 +135,11 @@ int dtp_download_file(uint32_t server_node, uint16_t payload_id,
130135
dtp_t *session = dtp_prepare_session(
131136
server_node,
132137
session_id,
133-
DTP_DEFAULT_THROUGHPUT,
134-
DTP_DEFAULT_TIMEOUT_S,
138+
throughput,
139+
timeout,
135140
payload_id,
136141
NULL, /* ctx - set below */
137-
DTP_DEFAULT_MTU,
142+
mtu,
138143
false, /* resume */
139144
0 /* keep_alive_interval */
140145
);

satdeploy-apm/src/deploy.pb-c.c

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ void satdeploy__deploy_response__free_unpacked
187187
assert(message->base.descriptor == &satdeploy__deploy_response__descriptor);
188188
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
189189
}
190-
static const ProtobufCFieldDescriptor satdeploy__deploy_request__field_descriptors[17] =
190+
static const ProtobufCFieldDescriptor satdeploy__deploy_request__field_descriptors[20] =
191191
{
192192
{
193193
"command",
@@ -393,15 +393,54 @@ static const ProtobufCFieldDescriptor satdeploy__deploy_request__field_descripto
393393
0, /* flags */
394394
0,NULL,NULL /* reserved1,reserved2, etc */
395395
},
396+
{
397+
"dtp_mtu",
398+
18,
399+
PROTOBUF_C_LABEL_NONE,
400+
PROTOBUF_C_TYPE_UINT32,
401+
0, /* quantifier_offset */
402+
offsetof(Satdeploy__DeployRequest, dtp_mtu),
403+
NULL,
404+
NULL,
405+
0, /* flags */
406+
0,NULL,NULL /* reserved1,reserved2, etc */
407+
},
408+
{
409+
"dtp_throughput",
410+
19,
411+
PROTOBUF_C_LABEL_NONE,
412+
PROTOBUF_C_TYPE_UINT32,
413+
0, /* quantifier_offset */
414+
offsetof(Satdeploy__DeployRequest, dtp_throughput),
415+
NULL,
416+
NULL,
417+
0, /* flags */
418+
0,NULL,NULL /* reserved1,reserved2, etc */
419+
},
420+
{
421+
"dtp_timeout",
422+
20,
423+
PROTOBUF_C_LABEL_NONE,
424+
PROTOBUF_C_TYPE_UINT32,
425+
0, /* quantifier_offset */
426+
offsetof(Satdeploy__DeployRequest, dtp_timeout),
427+
NULL,
428+
NULL,
429+
0, /* flags */
430+
0,NULL,NULL /* reserved1,reserved2, etc */
431+
},
396432
};
397433
static const unsigned satdeploy__deploy_request__field_indices_by_name[] = {
398434
1, /* field[1] = app_name */
399435
3, /* field[3] = appsys_node */
400436
14, /* field[14] = chunk_data */
401437
12, /* field[12] = chunk_seq */
402438
0, /* field[0] = command */
439+
17, /* field[17] = dtp_mtu */
403440
6, /* field[6] = dtp_server_node */
404441
7, /* field[7] = dtp_server_port */
442+
18, /* field[18] = dtp_throughput */
443+
19, /* field[19] = dtp_timeout */
405444
10, /* field[10] = expected_checksum */
406445
9, /* field[9] = expected_size */
407446
16, /* field[16] = file_mode */
@@ -416,7 +455,7 @@ static const unsigned satdeploy__deploy_request__field_indices_by_name[] = {
416455
static const ProtobufCIntRange satdeploy__deploy_request__number_ranges[1 + 1] =
417456
{
418457
{ 1, 0 },
419-
{ 0, 17 }
458+
{ 0, 20 }
420459
};
421460
const ProtobufCMessageDescriptor satdeploy__deploy_request__descriptor =
422461
{
@@ -426,7 +465,7 @@ const ProtobufCMessageDescriptor satdeploy__deploy_request__descriptor =
426465
"Satdeploy__DeployRequest",
427466
"satdeploy",
428467
sizeof(Satdeploy__DeployRequest),
429-
17,
468+
20,
430469
satdeploy__deploy_request__field_descriptors,
431470
satdeploy__deploy_request__field_indices_by_name,
432471
1, satdeploy__deploy_request__number_ranges,

satdeploy-apm/src/deploy.pb-c.h

Lines changed: 16 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

satdeploy/cli.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ def get_transport(
5555
backup_dir=backup_dir,
5656
zmq_pub_port=module.zmq_pub_port,
5757
zmq_sub_port=module.zmq_sub_port,
58+
dtp_mtu=module.dtp_mtu,
59+
dtp_throughput=module.dtp_throughput,
60+
dtp_timeout=module.dtp_timeout,
5861
)
5962
else:
6063
raise ValueError(f"Unknown transport type: {module.transport}")

0 commit comments

Comments
 (0)