Обрати внимание что каждый arg существует и "прилетает" вовсе не в
твоем коде, который ты написал. Он существует и прилетает только из
коллбэков (функций обратного вызова), которые дёргает сама LwIP.
Так вот, этот arg должен задавать ТЫ в момент обращения к LwIP на
установку callback'а. После этого LwIP запоминает его внутри себя.
И каждый раз когда LwIP изнутри себя "дёргает", вызывает
callback'ом уже ТВОЙ код, она-то и пеhедает внутрь твоего кода
запомненный внутри себя arg. Для чего это? Чтобы при callback'е передать внутрь твоих функций некий запомненный arg. Зачем? Потому что callback всего один, одна функция на всю прошивку. Но вызываться он может для многих случаев. Как ты отличишь внутри одной функции callback'а что именно сейчас обрабатывается в callback'е? Ответ: По собственному, заданному тобой ЗНАЧЕНИЮ в переменной arg, который прилетает из LwIP, но который ранее задавал ты.
Предоставление параметра в виде int или void* для callback'ов - давно известный и накатанный паттерн в большинстве программ (не только си и не только LwIp). Самое первое что вспоминается - параметр в _beginthread