Пишем простую нейронную сеть с использованием математики и Numpy

Зачем очередная статья про то, как писать нейронные сети с нуля? Увы, я не смог найти статьи, где были бы описаны теория и код с нуля до полностью работающей модели. Сразу предупреждаю, что тут будет много математики. Я предполагаю, что читатель знаком с основами линейной алгебры, частными производными и хотя бы частично, с теорией вероятностей, а также Python и Numpy. Будем разбираться с полносвязной нейронной сетью и MNIST.

Математика. Часть 1 (простая)

Что такое полносвязный слой (fully connected layer, FC layer)? Обычно говорят что-то в духе «Полносвязный слой — это слой, каждый нейрон которого соединён со всеми нейронами предыдущего слоя». Вот только непонятно что такое нейроны, как они соединены, особенно в коде. Сейчас я попробую разобрать это на примере. Вот пусть есть слой из 100 нейронов. Я знаю, что пока не объяснил, что это, но давайте просто представим, что есть 100 нейронов и у них есть вход, куда подаются данные, и выход, откуда они выдают данные. И на вход им подаётся чёрно-белая картинка 28х28 пикселей — всего 784 значения, если растянуть её в вектор. Картинку можно назвать входным слоем. Тогда чтобы каждый из 100 нейронов соединился с каждым «нейроном» или, если угодно, значением предыдущего слоя (то есть картинкой) нужно, чтобы каждый из 100 нейронов принял 784 значения исходной картинки. Например, для каждого из 100 нейронов достаточно будет умножить 784 значения картинки на какие-то 784 числа и сложить между собой, в результате выходит одно число. То есть это и есть нейрон:

$$display$$\text{Выход нейрона} = \text{какое-то число}_{1} \cdot \text{значение картинки}_1~+ \\ +~…~+~\text{какое-то число}_{784} \cdot \text{значение картинки}_{784} $$display$$

Тогда получится, что у каждого нейрона есть 784 числа, а всего этих чисел: (количество нейронов на этом слое) х (количество нейронов на предыдущем слое) =

$inline$100\times784$inline$

= 78 400 цифр. Эти числа обычно называют весами слоя. Каждый нейрон выдаст свою число и в итоге получится 100-мерный вектор, и на самом деле можно записать, что этот 100-мерный вектор получается умножением 784-мерного вектора (нашей исходной картинки) на матрицу весов размером

$inline$100\times784$inline$

:

$$display$$\boldsymbol{x}^{100} = W_{100\times784}\cdot \boldsymbol{x}^{784}$$display$$

Дальше получившиеся 100 чисел передаются дальше, на функцию активации — некоторую нелинейную функцию — которая воздействует на каждое число поотдельности. Например, сигмоида, гиперболический тангенс, ReLU и другие. Функция активации обязательно нелинейная, иначе нейронная сеть научится только простым преобразованиям.

Затем получившиеся данные вновь подаются на полносвязный слой, но уже с другим количеством нейронов, и вновь на функцию активации. Так происходит несколько раз. Последний слой сети — это слой, который выдаёт ответ. В данном случае, ответ — это информация о том, какая цифра на картинке.

Во время обучения сети необходимо чтобы мы знали, какая цифра изображена на картинке. То есть чтобы датасет был размечен. Тогда можно использовать ещё один элемент — функцию ошибки. Она смотрит на ответ нейронной сети и сравнивает с настоящим ответом. Благодаря этому нейронная сеть и учится.

Общая постановка задачи

Весь датасет — это большой тензор (тензором будем называть некоторый многомерный массив данных)

$inline$\boldsymbol{X} = \left[\boldsymbol{x}_1,\boldsymbol{x}_2,\ldots,\boldsymbol{x}_n \right]$inline$

, где

$inline$\boldsymbol{x}_i$inline$

— i-ый объект, например, картинка, которая тоже является тензором. Для каждого объекта есть

$inline$y_i$inline$

— правильный ответ на i-м объекте. В этом случае нейронную сеть можно представить как некоторую функцию, которая принимает на вход объект и выдает на нем какой-то ответ:

$$display$$F(\boldsymbol{x}_i) = \hat{y}_i$$display$$

Теперь давайте подробнее рассмотрим функцию

$inline$F(\boldsymbol{x}_i)$inline$

. Так как нейронная сеть состоит из слоев, то каждый отдельный слой — функция. А значит

$$display$$F(\boldsymbol{x}_i) = f_k(f_{k-1}(\ldots(f_1(\boldsymbol{x}_i)))) = \hat{y}_i$$display$$

То есть, в самую первую функцию — первый слой — подается картинка в виде некоторого тензора. Функция

$inline$f_1$inline$

выдает какой-то ответ — тоже тензор, но уже другой размерности. Этот тензор будет называться внутреннем представлением. Теперь это внутреннее представление подается на вход функции

$inline$f_2$inline$

, которая выдает свое внутреннее представление. И так далее, пока функция

$inline$f_k$inline$

— последний слой — не выдаст ответ

$inline$\hat{y}_i$inline$

.

Теперь, задача — обучить сеть — сделать так, чтобы ответ сети совпадал с правильным ответом. Для начала нужно измерить насколько нейронная сеть ошиблась. Измерять это будет функция ошибки

$inline$L(\hat{y}_i, y_i)$inline$

. Причем накладываем ограничения:

1.

$inline$\hat{y}_i \xrightarrow{} y_i \Rightarrow L(\hat{y}_i, y_i) \xrightarrow{} 0$inline$

2.

$inline$\exists ~ dL(\hat{y}_i, y_i)$inline$

3.

$inline$L(\hat{y}_i, y_i) \geq 0$inline$

Ограничение 2 наложим на все функции слоев

$inline$f_j$inline$

— пусть они все будут дифференцируемы.

Причем, на самом деле (об этом я умолчал) часть этих функции зависят от параметров — весов нейронной сети —

$inline$f_j(\boldsymbol{x}_i | \boldsymbol{\omega}_j)$inline$

. И вся идея заключается в том, чтобы подобрать такие веса, чтобы

$inline$\hat{y}_i$inline$

совпадал с

$inline$y_i$inline$

на всех объектах датасета. Отмечу, что веса есть не во всех функциях.

Итак, на чем мы остановились? Все функции нейронной сети дифференцируемы, функция ошибки тоже дифференцируема. Вспомним одно из свойств градиента — показывать направление роста функции. Воспользуемся этим, ограничениями 1 и 3, фактом, что

$$display$$ L(F(\boldsymbol{x}_i)) = L(f_k(f_{k-1}(\ldots(f_1(\boldsymbol{x}_i))))) = L(\hat{y}_i)$$display$$

и тем, что я умею считать частные производные и производные сложной функции. Теперь есть все что нужно, для того чтобы посчитать

$$display$$\frac{\partial L(F(\boldsymbol{x}_i))}{\partial \boldsymbol{\omega_j}} $$display$$

для любого i и j. Эта частная производная показывает направление, в котором нужно изменить

$inline$\boldsymbol{\omega_j}$inline$

, чтобы увеличить

$inline$L$inline$

. Чтобы уменьшить нужно сделать шаг в сторону

$inline$-\frac{\partial L(F(\boldsymbol{x}_i))}{\partial \boldsymbol{\omega_j}}$inline$

, ничего сложного.

Значит процесс обучения сети строится так: несколько раз в цикле проходим по всему датасету (это называется эпоха), для каждого объекта датасета считаем

$inline$L(\hat{y}_i, y_i)$inline$

(это называется forward pass) и считаем частную производную

$inline$\partial L$inline$

для всех весов

$inline$\boldsymbol{\omega_j}$inline$

, затем обновляем веса (это называется backward pass).

Замечу, что я еще не ввел никаких конкретных функций и слоев. Если на данном этапе не совсем ясно, что со всем этим делать, предлагаю продолжить чтение — математики станет больше, но теперь она будет идти с примерами.

Математика. Часть 2 (сложная)

Функция ошибки

Я начну с конца и выведу функцию ошибки для задачи классификации. Для задачи регрессии вывод функции ошибки хорошо описан в книге «Глубокое обучение. Погружение в мир нейронных сетей».

Для простоты, есть нейронная сеть (NN), которая отделяет фотографии котиков от фотографий собак, и есть набор фотографий кошек и собак, для которых есть правильный ответ

$inline$y_{true}$inline$

.

$$display$$NN(picture | \Omega) = y_{pred}$$display$$

Все что я буду делать дальше, очень похоже на метод максимального правдоподобия. Поэтому основная задача — найти функцию правдоподобия. Если опустить подробности, то такую функцию, которая сопоставляет предсказание нейронной сети и правильный ответ, и, если они совпадают, выдает большое значение, если же нет, наоборот. На ум приходит вероятность правильного ответа при заданных параметрах:

$$display$$p(y_{pred} = y_{true} | \Omega)$$display$$

А теперь сделаем некоторый финт, который вроде бы ни от куда не следует. Пусть нейронная сеть выдает ответ в виде двумерного вектора, сумма значений которого равна 1. Первый элемент этого вектора можно назвать мерой уверенности, что на фотографии кот, а второй элемент — мерой уверенности, что на фотографии пёс. Да это же почти вероятности!

$$display$$NN(picture | \Omega) = \left[\begin{matrix}p_0\\p_1\\\end{matrix}\right]$$display$$

Теперь функцию правдоподобия можно переписать в виде:

$$display$$p(y_{pred} = y_{true} | \Omega) = p_\Omega (y_{pred})^t_{0} * (1 — p_\Omega (y_{pred}))^t_{1} = \\ p_0^{t_0} * p_1^{t_1}$$display$$

Где

$inline$t_0, t_1$inline$

метки верного класса, например, если

$inline$y_{true} = cat$inline$

, то

$inline$t_0 == 1, t_1 == 0$inline$

, если

$inline$y_{true} = dog$inline$

, то

$inline$t_0 == 0, t_1 == 1$inline$

. Таким образом всегда рассматривается вероятность класса, который должен был быть предсказан нейронной сетью (но не обязательно был предсказан ею). Теперь это можно обобщить на любое количество классов (например, m классов):

$$display$$p(y_{pred} = y_{true} | \Omega) = \prod_0 ^m p_i^{t_i}$$display$$

Однако, в любом датасете есть много объектов (например, N объектов). Хочется, чтобы на каждом или большинстве объектов нейронная сеть выдавала верный ответ. И для этого нужно перемножить результаты формулы выше для каждого объекта из датасета.

$$display$$MaximumLikelyhood = \prod_{j=0} ^N \prod_{i=0} ^m p_{i,j}^{t_{i,j}}$$display$$

Чтобы получить хорошие результаты, эту функцию нужно максимизировать. Но, во-первых, минимизировать круче, потому что у нас есть стохастический градиентный спуск и все плюшки для него — просто припишем минус, а, во-вторых, с огромным произведением работать затруднительно — логарифмируем.

$$display$$CrossEntropyLoss = — \sum\limits_{j=0}^{N} \sum\limits_{i=0}^{m}t_{i,j}\cdot\log(p_{i,j})$$display$$

Замечательно! Получилась перекрестная энтропия или, в бинарном случае, logloss. Эту функцию легко считать и еще легче дифференцировать:

$$display$$\frac{\partial CrossEntropyLoss}{\partial p_j} = — \frac{\boldsymbol{t_j}}{\boldsymbol{p_{j}}}$$display$$

Дифференцировать нужно для алгоритма обратного распространения ошибки. Замечу, что функция ошибки не изменяет размерность вектора. Если, как в случае MNIST, на выходе получается 10-мерный вектор ответов, то и при вычислении производной получится 10-мерный вектор производных. Ещё одна интересная вещь то, что только один элемент производной не будет равен нулю, при котором

$inline$t_{i,j} \neq 0$inline$

, то есть при правильном ответе. И чем меньше вероятность верного ответа предсказала нейронная сеть на данном объекте, тем больше на нем будет функция ошибки.

Функции активации

На выходе каждого полносвязного слоя нейронной сети обязательно должна присутствовать нелинейная функция активации. Без неё невозможно обучить содержательную нейронную сеть. Если забежать вперед, то полносвязный слой нейронной сети — это просто умножение входных данных на матрицу весов. В линейной алгебре это называется линейным отображением — некоторая линейная функция. Комбинация линейных функций — тоже линейная функция. Но это значит, что такая функция может аппроксимировать только линейные функции. Увы, это не то, зачем нужны нейронные сети.

Softmax

Обычно эта функция используется на последнем слое сети, так как она превращает вектор с последнего слоя в вектор «вероятностей»: каждый элемент вектора лежит от 0 до 1 и их сумма равна 1. Она не меняет размерность вектора.

$$display$$Softmax_i = \frac{e^{x_i}}{\sum \limits_{j} e^{x_j}}$$display$$

Теперь перейдем к поиску производной. Так как

$inline$\boldsymbol{x}$inline$

— вектор, и в знаменателе всегда присутствуют все его элементы, то при взятии производной получим якобиан:

$$display$$J_{Softmax} = \begin{cases} x_i — x_i \cdot x_j, i = j\\ — x_i \cdot x_j, i \neq j \end{cases}$$display$$

Теперь про backpropagation. От предыдущего слоя (обычно это функция ошибки) приходит вектор производных

$inline$\boldsymbol{dz}$inline$

. В случае если

$inline$\boldsymbol{dz}$inline$

пришел от функции ошибки на MNIST,

$inline$\boldsymbol{dz}$inline$

— 10-мерный вектор. Тогда якобиан имеет размерность 10х10. Чтобы получить

$inline$\boldsymbol{dz_{new}}$inline$

, который пойдет далее, на предыдущий слой (не забываем, что мы идем от конца к началу сети при обратном распространении ошибки), нужно умножить

$inline$\boldsymbol{dz}$inline$

на

$inline$J_{Softmax}$inline$

(строка на столбец):

$$display$$dz_{new} = \boldsymbol{dz} \times J_{Softmax}$$display$$

На выходе получаем 10-мерный вектор производных

$inline$\boldsymbol{dz_{new}}$inline$

.

ReLU

$$display$$ReLU(x) = \begin{cases} x, x > 0\\ 0, x < 0 \end{cases}$$display$$

Массово использовать ReLU стали после 2011 года, когда вышла статья «Deep Sparse Rectifier Neural Networks». Однако, такая функция была известна и ранее. К ReLU применимо такое понятие, как «сила активации» (подробнее об этом можно почитать в книге «Глубокое обучение. Погружение в мир нейронных сетей»). Но главная особенность, которая делает ReLU привлекательнее других функций активации — простое вычисление производной:

$$display$$d(ReLU(x)) = \begin{cases} 1, x > 0\\ 0, x < 0 \end{cases}$$display$$

Таким образом ReLU вычислительно эффективнее других функций активации (сигмоида, гиперболический тангенс и др.).

Полносвязный слой

Теперь время обсудить полносвязный слой. Наиболее важный из всех остальных, потому что именно в этом слое находятся все веса, которые и нужно настроить для того, чтобы нейронная сеть работала хорошо. Полносвязный слой это просто-напросто матрица весов:

$$display$$W = |w_{i,j}|$$display$$

Новое внутреннее представление получается, когда матрица весов умножается на столбец входных данных:

$$display$$\boldsymbol{x}_{new} = W\cdot \boldsymbol{x}$$display$$

Где

$inline$\boldsymbol{x}$inline$

имеет размер

$inline$input\_shape$inline$

, а

$inline$x_{new}$inline$

$inline$output\_shape$inline$

. Например,

$inline$\boldsymbol{x}$inline$

— 784-мерный вектор, а

$inline$\boldsymbol{x}_{new}$inline$

— 100-мерный вектор, тогда матрица W имеет размер 100х784. Получается, что на этом слое находится 100х784 = 78 400 весов.

При обратном распространении ошибки нужно взять производную по каждому весу этой матрицы. Упростим задачу и возьмем только производную по

$inline$w_{1,1}$inline$

. При умножении матрицы и вектора первый элемент нового вектора

$inline$\boldsymbol{x}_{new}$inline$

равен

$inline$x_{new~1} = w_{1,1} \cdot x_1 + … + w_{1,784} \cdot x_{784} $inline$

, а производная

$inline$x_{new~1}$inline$

по

$inline$w_{1,1}$inline$

будет просто

$inline$x_1$inline$

, нужно всего лишь взять производную от суммы выше. Аналогично происходит для всех остальных весов. Но это еще не алгоритм обратного распространения ошибки, пока это просто матрица производных. Нужно вспомнить, что от следующего слоя на этот (ошибка идет от конца к началу) приходит 100-мерный вектор градиента

$inline$d\boldsymbol{z} $inline$

. Первый элемент этого вектора

$inline$dz_1 $inline$

будет умножаться на все элементы матрицы производных, которые «участвовали» в создании

$inline$x_{new~1}$inline$

, то есть на

$inline$x_1, x_2, … , x_{784}$inline$

. Аналогично и остальные элементы. Если перевести это на язык линейной алгебры, то это записывается так:

$$display$$\frac{\partial L}{\partial W} = (d\boldsymbol{z},~dW) = \left( \begin{matrix} dz_{1} \cdot \boldsymbol{x} \\ … \\ dz_{100} \cdot\boldsymbol{x} \end{matrix}\right)_{100}$$display$$

На выходе получается матрица 100х784.

Теперь нужно понять, что же передавать на предыдущий слой. Для этого и для большего понимания что вообще сейчас произошло, я хочу записать то, что случилось при взятии производных на этом слое чуть-чуть другим языком, уйти от конкретики «что на что умножается» к функциям (опять).

Когда я хотел настроить веса, то я хотел взять производную функции ошибки по этим весам:

$inline$\frac{\partial L}{\partial W}$inline$

. Выше было показано, как брать производные по функциям ошибки и функциям активации. Поэтому можно рассмотреть такой случай (в

$inline$d\boldsymbol{z}$inline$

уже сидят все производные от функции ошибки и функций активации):

$$display$$\frac{\partial L}{\partial W} = d\boldsymbol{z} \cdot \frac{\partial \boldsymbol{x}_{new}(W)}{\partial W}$$display$$

Так можно сделать, потому что можно рассмотреть

$inline$\boldsymbol{x}_{new}$inline$

, как функцию от W:

$inline$\boldsymbol{x}_{new} = W\cdot \boldsymbol{x}$inline$

.
Можно подставить это в формулу выше:

$$display$$\frac{\partial L}{\partial W} = d\boldsymbol{z} \cdot \frac{\partial W\cdot \boldsymbol{x}}{\partial W} = d\boldsymbol{z} \cdot E \cdot \boldsymbol{x}$$display$$

Где E матрица состоящая из единиц (НЕ единичная матрица).

Теперь когда нужно взять производную от предыдущего слоя (пусть для простоты выкладок это тоже будет полносвязный слой, но в общем случае это ничего не меняет), то нужно рассмотреть

$inline$\boldsymbol{x}$inline$

, как функцию от предыдущего слоя

$inline$\boldsymbol{x}(W_{old})$inline$

:

$$display$$\begin{gathered} \frac{\partial L}{\partial W_{old}} = d\boldsymbol{z} \cdot \frac{\partial \boldsymbol{x}_{new}(W)}{\partial W_{old}} = d\boldsymbol{z} \cdot \frac{\partial W\cdot \boldsymbol{x}(W_{old})}{\partial W_{old}} = \\ = d\boldsymbol{z} \cdot \frac{\partial W\cdot W_{old}\cdot\boldsymbol{x}_{old}}{\partial W_{old}} = d\boldsymbol{z} \cdot W \cdot E \cdot \boldsymbol{x}_{old} = \\ = d\boldsymbol{z}_{new} \cdot E \cdot \boldsymbol{x}_{old} \end{gathered}$$display$$

Именно

$inline$d\boldsymbol{z}_{new} = d\boldsymbol{z} \cdot W$inline$

и нужно отправить на предыдуший слой.

Код

В первую очередь эта статья нацелена на объяснение математики нейронных сетей. Коду я уделю совсем немного времени.

Это пример реализации функции ошибки:

class CrossEntropy:     def forward(self, y_true, y_hat):         self.y_hat = y_hat         self.y_true = y_true         self.loss = -np.sum(self.y_true * np.log(y_hat))         return self.loss      def backward(self):         dz = -self.y_true / self.y_hat         return dz 

Класс имеет методы для прямого и обратного прохода. В момент прямого прохода экземпляр класса сохраняет данные внутри слоя, а в момент обратного прохода использует их для расчета градиента. Таким же образом построены и остальные слои. Благодаря этому становится возможным написать полносвязную нейронную в таком стиле:

class MnistNet:     def __init__(self):         self.d1_layer = Dense(784, 100)         self.a1_layer = ReLu()         self.drop1_layer = Dropout(0.5)          self.d2_layer = Dense(100, 50)         self.a2_layer = ReLu()         self.drop2_layer = Dropout(0.25)          self.d3_layer = Dense(50, 10)         self.a3_layer = Softmax()     def forward(self, x, train=True):         ...     def backward(self,                  dz,                  learning_rate=0.01,                  mini_batch=True,                  update=False,                  len_mini_batch=None):         ... 

Полный код можно посмотреть тут.
Также советую изучить эту статью на Хабре.

Заключение

Надеюсь, я смог объяснить и показать, что за нейронными сетями стоит довольно простая математика и, что это совершенно не страшно. Тем не менее для более глубокого понимания стоит попробовать написать свой «велосипед». Исправления и предложения с радостью почитаю в комментариях.


ссылка на оригинал статьи https://habr.com/ru/post/460589/

«Универсал» в команде разработки: польза или вред?

image
Всем привет! Меня зовут Людмила Макарова, я менеджер разработки в УБРиР и треть моей команды – «универсалы».

Признайте: каждый Tech Lead мечтает о кросс-функциональности внутри своей команды. Ведь это так круто, когда один человек способен заменить трех, да еще и сделать это качественно, не сдвигая сроки. И, что немаловажно, это обеспечивает экономию ресурсов!
Звучит очень заманчиво, но так ли это на самом деле? Давайте попробуем разобраться.

Кто он, наш предвосхититель ожиданий?

Под понятием «универсал» обычно понимают членов команды, сочетающих в себе больше одной роли, например, разработчик-аналитик.

Взаимодействие команды и результат ее работы зависят от профессиональных и личностных качеств участников.

По hard skills все ясно, а вот soft skills заслуживают особого внимания. Они помогают найти подход к сотруднику и направить его именно на ту задачу, на которой он будет максимально полезен.

Существует много статей о всевозможных типах личностей представителей IT-индустрии. Опираясь на свой опыт, я бы поделила IT-универсалов на четыре категории:

1. «Универсал – всемогущий».

Такие есть везде. Они всегда проявляют большую активность, хотят быть в центре внимания, постоянно интересуются у коллег, нужна ли их помощь, иногда даже могут раздражать. Их интересуют только значимые задачи, участие в которых даст простор для творчества и сможет потешить самолюбие.

В чем сильны:
— способны решать сложные задачи;
— глубоко погружаются в проблему, «копают» и добиваются результата;
— обладают пытливым умом;

Но:
— эмоционально лабильны;
— слабо управляемы;
— имеют свою непоколебимую точку зрения, которую очень сложно изменить;
— сложно заставить сделать простое дело. Легкие задачи задевают самолюбие всемогущих.

2. «Универсал – разберусь и сделаю».

Таким людям достаточно мануала и немного времени – и они решат вопрос. Обычно они имеют за спиной большой бэкграунд в качестве DevOps. Такие универсалы не утруждают себя проектированием и предпочитают использовать метод разработки только на основе исключительно своего опыта. Могут запросто закуситься с техлидом по поводу выбранного варианта реализации задачи.

В чем сильны:
— самостоятельны;
— стрессоустойчивы;
— компетентны во многих вопросах;
— эрудированы – с ними всегда есть о чем поговорить

Но:
— часто нарушают обязательства;
— склонны все усложнять: решают таблицу умножения интегрированием по частям;
— качество работы низкое, все получается с 2-3 раза;
— постоянно сдвигают сроки, потому что на самом деле все оказывается не так-то и просто.

3. «Универсал – ладно, давайте я, раз больше некому».

Сотрудник неплохо разбирается в нескольких областях и имеет соответствующий опыт. Но ему не удается стать профессионалом ни в одной из них, потому что его часто используют в качестве спасательного круга, затыкая дыры по текущим задачам. Податлив, исполнителен, считает себя востребованным, однако таковым не является.
Практический идеальный сотрудник. Скорее всего, у него есть направление, которое ему больше нравится, но из-за размытия компетенций развития не происходит. В результате человек рискует стать невостребованным и эмоционально выгоревшим.

В чем сильны:
— ответственны;
— нацелены на результат;
— спокойны;
— полностью контролируемы;

Но:
— показывают средний результат из-за низкого уровня компетенций;
— не могут решать сложные и абстрактные задачи.

4. «Универсал – мастер своего дела».

Человек с серьезным бэкграундом разработчика, обладает системным мышлением. Педантичен, требователен к себе и команде. Любая задача с его участием может разрастись до бесконечности, если не обозначить границы.
Хорошо знаком с архитектурой, выбирает метод технической реализации, тщательно анализируя влияние выбранного решения на текущую архитектуру. Скромен, не амбициозен.

В чем сильны:
— показывают высокое качество работы;
— способны решить любую задачу;
— очень работоспособны.

Но
— нетерпимы к мнению других;
— максималисты. Стараются все сделать правильно, а это увеличивает сроки разработки.

Что имеем на практике?

Посмотрим, как чаще всего объединяются роли и компетенции. За отправную точку возьмем стандартную команду разработки: PO, менеджер разработки (техлид), аналитики, программисты, тестировщики. Владельца продукта и техлида считать не будем. Первого – из-за отсутствия технических компетенций. Второй, если в команде проблемы, как раз должен уметь делать все.

Наиболее распространенный вариант объединения/слияния/совмещения компетенций – разработчик-аналитик. Также очень часто встречаются аналитик-тестировщик и «три в одном».

На примере своей команды покажу, в чем плюсы и минусы коллег-универсалов. В моей команде их треть, и я их очень люблю.
От PO поступила срочная задача по внедрению новых тарифов в существующий продукт. В моей команде 4 аналитика. На тот момент один находился в отпуске, другой заболел, а остальные занимались реализацией стратегических задач. Если бы я выдернула их, это неизбежно сорвало бы сроки реализации. Остался единственный выход: использовать «секретное оружие» – универсала разработчика–аналитика, который владел нужной предметной областью. Назовем его Анатолий.
Его тип личности – «универсал – разберусь и сделаю». Конечно, он долго пытался объяснить, что у него «полный бэклог своих задач», но моим волевым решением был отправлен на решение срочной задачи. И Анатолий справился! Он провел постановку и выполнил реализацию в срок, а заказчики остались довольны.

На первый взгляд все удалось. Но через несколько недель по этому продукту вновь возникли требования по доработке. Теперь постановкой по этой задаче занимался «чистый» аналитик. На этапе тестирования новой разработки мы долго не могли понять, почему у нас возникают ошибки по привязке новых тарифов и только потом, размотав весь клубок, докопались до истины. Мы потратили кучу времени и сорвали сроки.

Проблема заключалась в том, что многие скрытые моменты и подводные камни остались только в голове нашего универсала и не были перенесены на бумагу. Как позже объяснил Анатолий, он слишком торопился. Но наиболее вероятен вариант, что он наткнулся на проблемы уже при разработке и просто их обошел, нигде это не отразив.

Была и другая ситуация. Сейчас у нас только один тестировщик, поэтому некоторые задачи приходится тестировать аналитикам, в том числе – универсалам. Поэтому один таск я отдала условному Федору – «универсалу – ладно, давайте я, раз больше некому».
Федор – «три в одном», но по этой задаче уже был выделен разработчик. Значит, Феде надо было совместить в себе только аналитика и тестировщика.

Требования собраны, спецификация передана в разработку, пришло время тестировать. Федор знает дорабатываемую систему «как свои пять пальцев» и досконально прорабатывал текущие требования. Поэтому он не стал утруждать себя написанием тестовых сценариев, а провел тестирование на то, «как система должна работать», потом – передал пользователям.
Тест завершился, доработка ушла на пром. Позже выяснилось, что система не только приостанавливает проведение платежей на определенные балансовые счета, но и блокирует проведение платежей с очень редких внутренних счетов, которые не должны были участвовать в этом.
Это случилось из-за того, что Федор не провел проверку на то, как «не должна работать система», не составил тест-план, чек-листы. Он решил сэкономить на сроках и положился на собственное чутьё.

Как работаем с проблемами?

Подобные ситуации влияют на эффективность работы команды, качество выпускаемых релизов и удовлетворенность заказчиков. Поэтому их нельзя оставлять без внимания и анализа причин.

1. По каждой задаче, вызвавшей сложности, я прошу заполнить унифицированную форму: карту ошибок, которая позволяет выявить этап, на котором произошла «просадка»:
image
2. После выявления узких мест, с каждым сотрудником, повлиявшим на проблему, проводится мозговой штурм «Что изменить?» (частные случаи мы не рассматриваем на ретро), по итогам которого рождаются конкретные действия (для каждого типа личности свои) со сроками.
3. Мы ввели правила взаимодействия внутри команды. Например, договорились обязательно фиксировать всю информацию о ходе задачи в системе управления проектов. При изменении/выявлении артефактов в процессе разработки нужно отображать это в базе знаний и итоговой версии ТЗ.
4. Контроль стал проводиться на каждом этапе (особенное внимание уделяется проблемным этапам в прошлом) и автоматически по результатам выполнения следующей задачи.
5. Если результат по следующей задаче не изменился, то рассматриваемого универсала не ставлю в ту роль, с которой он плохо справляется. Стараюсь оценить его способность и желание к развитию компетенций в этой роли. Если не нахожу отклика, оставляю его в той роли, которая ему ближе.

Что в итоге получилось?

Процесс разработки стал прозрачнее. Уменьшился BUS-фактор. Члены команды, работая над ошибками, становятся более мотивированными, улучшают свою карму. Мы постепенно повышаем качество наших релизов.
image

Выводы

У сотрудников-универсалов есть свои плюсы и минусы.

Достоинства:

  • можно в любой момент закрыть провисающую задачу или разрешить срочный баг в короткие сроки;
  • комплексный подход при решении задачи: исполнитель смотрит на нее со стороны всех ролей;
  • универсалы могут практически все делать одинаково хорошо.

Недостатки:

  • растет BUS-фактор;
  • размываются основные компетенции, присущие роли. Из-за этого снижается качество работы;
  • повышается вероятность сдвига сроков, т.к. отсутствует контроль по каждому этапу. Также возникают риски выращивания «звезды»: сотрудник уверен, что он лучше знает, что он – профи;
  • увеличивается риск профессионального выгорания;
  • много важной информации о проекте может остаться только «в голове» у сотрудника.

Как видите, недостатков больше. Поэтому универсалами я пользуюсь только в том случае, если не хватает ресурсов, а задача достаточно срочная. Или человек обладает компетенциями, которых недостаточно у других, а на кону стоит качество.

Если в совместной работе над задачей соблюдается правило распределения ролей, то качество работы растет. На проблемы мы смотрим с разных сторон, взгляд не замыливается, всегда появляются свежие мысли. При этом каждый участник команды имеет все возможности для профессионального роста и расширения своих компетенций.
Я считаю, что самое важное – ощущать свою причастность к процессу, заниматься своей работой, постепенно увеличивая широту своих компетенций. Тем не менее, универсалы в команде приносят пользу: главное сделать так, чтобы они эффективно совмещали в себе разные роли.

Желаю всем самоорганизующейся команды «универсалов–мастеров своего дела»!


ссылка на оригинал статьи https://habr.com/ru/post/460593/

Новости из мира OpenStreetMap № 468 (02.07.2019-08.07.2019)

Logo

OSM на праздновании своего дня рождения в 2006 году в Лондоне – карта с правильной атрибуцией (на тот момент)
1 | Map data OpenStreetmap OdbL

О нас

  • ОШИБКА: В прошлом выпуске WeeklyOSM №467 мы писали: «Издание «Japan Times» сообщает, что не так давно появилась современная цифровая карта Бенина (государство в Западной Африке), которая заменила собой старую карту 1957 года.» Упоминание OSM в контексте этой новости было неверным. Ссылка вела в один из городов Нигерии, а не Бенина. Более того, геоданные, созданные в рамках этого проекта под руководством IGN France International, как и во многих бывших французских колониях, к сожалению, являются закрытыми, несмотря на то, что разработка подобных проектов частично финансируется государственными фондами Евросоюза.

Картографирование

  • Джозеф Айзенберг переписал вики-страницу «Хорошие практики» и начал обсуждение своих изменений в общем списке рассылки Talk. Несмотря на то, что почти все его дополнения, за редким исключением, были одобрены большинством, он был подвергнут критике за то, что отредактировал статью до того, как обсудил это с сообществом.
  • Джозеф Айзенберг объявил о начале голосования за предлагаемый им к использованию тег waterway=tidal_channel.
  • Пользователь higa4 изучил (ja), как обстояли дела в Японии с картографированием в первом полугодии 2019 года.
  • Манинг Самбале рассказал, что он вместе с другими коллегами с Филиппин побывал в Лупанг Аренду (муниципалитет Тайтай, провинция Ризай), где они занимались картографированием. Также они снимали панорамы улиц и делали аэрофотоснимки с помощью дронов, чтобы помочь местным властям в их программах по предупреждению и ликвидации чрезвычайных ситуаций. Помимо этого он отметил, что в следующем месяце на Филиппинах планируется серия бесплатных семинаров, которые пройдут в рамках конференции Pista Ng Mapa. Организованы они будут той же командой волонтеров, которая снимала с дронов Лупанг Аренду.
  • Обсуждалось предложение пользователя SilentSpike: сделать в iD предупреждение, когда landuse соединяется с автомагистралью. Как обычно, на этот счет есть разные мнения.

Сообщество

  • [1] 9 августа 2019 года OpenStreetMap отметит свой 15-й день рождения. Информация о праздничных мероприятиях собирается на WikiOSM.
  • Пользователь SeverinGeo опубликовал в своем твиттере фотографию с двухнедельных курсов по OSM и геоматике, которые проходили в столице Мавритании Нуакшоте. Они проводились для членов местного сообщества OSM, исследователей и представителей местных органов власти. Курсы были организованы при поддержке нигерийской и сенегальской общин при поддержке международной организации «Франкофония».
  • В 2017 году Зои Гарднер провела опрос по гендерным и некоторым другим демографическим среди картографов, а также проанализировала их профили в онлайн-сервисе «How did you contribute to OpenStreetMap?». Ее подробные выводы не так давно были опубликованы в научном журнале. Как оказалось, мужчины были более активными картографами. Но при этом между полами не было существенных различий в использовании тегов, которые на тот момент отображались в HDYC.
  • У форума OSM теперь есть стиль, который дружит со стартфонами, — Victory. Вы можете включить его в своем профиле на форуме в разделе “Показать” (Display).
  • Команда Grab на Филиппинах успешно провела картатон и написала об этом в блоге.
  • Harry Potter Wizards Unite — это новая игра дополненной реальности, использующая местоположения пользователя, от Niantic, создателя Ingress и Pokémon Go. Пользователь Грегори играл в эту игру и транслировал это на своем youtube-канале Mapper Diaries. Он также посмотрел, как она использует данные OpenStreetMap.
  • 22 июня в Москве (Россия) прошла оффлайн-картопати в поселке Коммунарка, где не так давно была открыта новая станция метро. В акции приняло участие 5 человек. Они неспешно обошли несколько районов этого поселка и собрали достаточно много информации. Редактирование карты этой территории в OSM — в процессе.

Фонд OpenStreetMap

  • Член Совета OSMF Йост Шуппе объявил, что теперь Совет будет проводить регулярные опросы перед каждым крупным мероприятием OSM. Это будет делаться не с целью повышения популярности Совета, а для того, чтобы ознакомиться с мнением людей, которых иначе никто никогда не услышит.

События

  • До 21 июля продлена скидка на раннюю покупку билетов на конференцию «State of the Map«.
  • Команда SotM начала сбор карт и постеров для выставки «Постеры, отзовитесь!», которая пройдет в этом году во время конфереции «State of the Map» в Гейдельберге (Германия). Отправить свою работу можно до 18 августа 2019 года. Кстати, уже опубликована программа конференции.
  • Отделение некоммерческой организации OSGeo (ja) в Японии объявило о проведении 13 и 14 сентября конференции FOSS4G Niigata (ja) и начале приема заявок на выступления. Заявки принимаются до 31 июля. Обращаем ваше внимание, что в этом году конференция пройдет не в Токио, а в Ниигате.
  • AGIT-2019 (перевод) — симпозиум и выставка прикладной геоинформатики, который прошел неделю назад в Зальцбурге (Австрия). На нем работал информационный стенд OSM и OSGeo, который был создан и установлен Маркусом и Андреасом. Они целыми днями отвечали на достаточно сложные вопросы посетителей. Андреас, он же Geologist, делал ежедневный отчет с этого события. Пожалуйста, почитайте его посты о том, как они приехали (перевод) в первый день (перевод), дне OSGeo (перевод), втором дне и пятнице (перевод). Маркус (ник ScubbX) тоже написал свой отчет (перевод).
  • GeoMundus — бесплатная международная конференция о геопространственных технологиях, геоинформатике и науках о Земле, организованная студентами магистратуры Erasmus Mundus в области геопространственных технологий. Сейчас на нее идет регистрация. Конференция состоится 29 и 30 ноября в университете Жауме I в Кастельон-де-ла-Плана (Испания).
  • Эрвин Оларио приглашает жителей Азии на местную открытую картографическую конференцию «Pista ng Mapa» (Фестиваль карт). Она пройдет 1-3 августа 2019 года в Университете Фонда в городе Думагете (Филиппины).

Гуманитарный OSM

  • Сейчас HOT рисует контуры зданий для измерения риска воздействия в Танзании. Для исследования картографы отрисовали 10955 зданий, часть из них была собрана 20 картографами «в полях». В блоге рассказывается об истории проекта, как собирались данные, как они будут использованы, а также о стоящих перед командой исследователей задачах.

Образование

  • Жан-Франсуа Перрат опубликовал(fr) руководство по организации картатона или группового занятия в классе. Помимо основ и доступных инструментов он рассказывает о разных способах активностей в классе. (автоматический перевод)

Карты

Переходим на OSM

  • Службы гражданской защиты на Азорских островах использовали OpenStreetMap, по крайней мере, во время учений.
  • «Федерация велосипедного спорта России» при подготовке буклета, посвященного чемпионату и первенству по велоспорту (шоссе) России, который был в конце июня (26-30 июня) в Белгороде, использовала карты OSM.

Открытые данные

  • Николай Джанакиев сделал онлайн-презентацию, где сравнил Викиданные и OSM..
  • Европейская комиссия опубликовала карту на основе OSM, отображающую местоположения компаний в ЕС, которые торгуют с МЕРКОСУР — южноамериканским торговым блоком.

Программное обеспечение

  • Разработчики Maps.Me значительно упростили процесс установки генератора карт для своего приложения. Теперь он выполнен в виде docker-контейнера, что позволяет самостоятельно собирать свежие карты для Maps.Me даже не опытному пользователю. Пока это возможно только в Linux.
  • Матеуш Кониечжи опубликовал результаты тестирования взаимодействия новых пользователей со StreetComplete (UX-тестирование).

Программирование

  • Теперь пользователи iD могут менять стиль карты во время редактирования. Разработчик iD Куинси Морган назвал эту функцию, которая похожа на то, что назывется «стили карты» в JOSM, «линзами».
  • Энди Аллан в своем блоге рассказал об изменениях, которые произошли на веб-сайте OSM/API в июне. Среди прочего, была улучшена обработка загрузок GPX-треков, а также введен новый запрос /api/versions. С помощью этого запроса можно узнать, какие версии API сейчас поддерживаются, а также позволяет запускать несколько версий API параллельно.

Релизы

  • Команда iD выпустила новую версию популярного редактора — v2.15.3. Об изменениях этой версии, которая уже используется osm.org, можно прочитать на GitHub.

Знаете ли вы …

  • … что Ватикан — источник многих тайн. Площадь небольшой страны, похоже, одна из них. Фрэнк Гаваэртс утверждает, что и в Википедия и «каждый отдельный источник… сообщают, что ее площадь — 44 га, даже britannica.com», но плагин JOSM составляет всего 0,49 км².
  • Вы, вероятно, видели изображение недели на главной странице WikiOSM. Но знаете ли вы, как туда предложить изображение? Это довольно просто.
  • …… что вы можете сделать рендер всей планеты в консоли? Вы можете получить доступ к демо-серверу через telnet или сделать это у себя на компьютере.
  • …… как отмечать виды топлива на АЗС? Рекомендуется использовать общие названия для различных типов топлива вместо местных названий или марок, для того чтобы обеспечить согласованность данных по всему миру. В WikiOSM отмечены эти значения, но на деле в общей сложности используется более 500 различных тегов “fuel:*”. Большинство из них недокументированы и используются всего лишь несколько раз.
  • …… про карту маяков, которая показывает, как они выглядят и мигают? В проекте GitHub используется Seark:light:sequence, а также теги Seaark:light:range и Seaark:light:color.
  • …что российская компания NextGIS сделала информационную система культурного и исторического наследия Ростовской земли (Ярославская область, Россия). На карте вы можете найти исторические сакральные места этой территории, усадьбы и даже места, где проживали знахари.
  • …что российский мапер FreeExec сделал достаточно много разных валидаторов? Схема электроснабжения РФ, валидатор подстанций напряжением свыше 35кВ, железнодорожные станций России и многое другое — вы можете найти на его личном сайте.

OSM в СМИ

  • Валерий Трубин продолжает серию интервью с российскими маперами. На этот раз он побеседовал с муниципальным чиновником из Тольятти Еленой Балашовой, которая разрешила данные с ЕМГИС использовать в OSM, а также с мапером Антоном Беличковым из Магнитогорска, посвятившего OSM 10 лет своей жизни.

Другие «гео» события

  • Алекс Парсонс написал в твиттере об исследовании, авторы которого проанализировали проблемы, оставляемые пользователями на сайте fixmystreet, чтобы выяснить: существует ли разница в отчетности между полами. Они обнаружили, что мужчины чаще сообщают о проблемах, связанных с вождением, а женщины — с ходьбой.
  • Во Франции генеральный совет по окружающей среде и устойчивому развитию опубликовал (перевод)доклад, в котором указывается, что префектуры довольно свободно интерпретировали возможность пересмотра гидрографических карт IGN, исключив многие малые реки. В стране, где открытые данные считаются важными, последовало много критических замечаний (1 перевод, 2 перевод, 3 перевод, 4 перевод) (fr), в которых подчеркивалось, что таким образом власти пытаются избежать соблюдения экологического законодательства в отношении этих рек.
  • К. М. Александр извлек изображения из старых карт, таких как Isola di Malta 1686 года или Terræ Sanctæ 1660 года, и сделал их доступными под лицензией CC BY 4.0.
  • Интернет-портал NZZ рассказывает о влиянии Google Maps на территориальные претензий и пограничные конфликты (“война Google Maps”), а также том, что произойдет, если целый город исчезнет по ошибке на месяц… (автоматическийё перевод)
  • В The Guardian вышла статья о приложении Guthook Guides, которое предоставляет информацию о походах, диких регионах и тропах по всему миру, а также о непредвиденных последствиях, вызванных растущей зависимостью пользователей от своих телефонов при навигации по пустыне.
  • Майк пишет (перевод) на своей домашней странице #geoObserver, что, несмотря на исчезновение одного метода, позволяшего создавать карту оснований зданий из OSM с помощью запроса через сервис Overpass turbo, все же это можно сделать достаточно просто в QGIS.
  • Видео о новых возможностях QGIS 3.8 (Zanzibar).


Общение российских участников OpenStreetMap идёт в чатике Telegram и на форуме. Также есть группы в социальных сетях ВКонтакте, Facebook, но в них в основном публикуются новости.

Присоединяйтесь к OSM!


Предыдущие выпуски: 467, 466, 465, 464, 463


ссылка на оригинал статьи https://habr.com/ru/post/460599/

Получение root на роутере Tenda Nova MW6

Началось всё с того, что польстившись на распродажу и новые buzz words — я приобрел wifi mesh систему, дабы покрыть все уголки загородного дома и прилегающего участка. Все бы ничего, но одна проблема раздражала. А с учетом того, что я сел на больничный на несколько дней — довела меня до root доступа к данному роутеру.

КДПВ

Проблема

Ради интереса, приобрел два набора по три кубика Tenda Nova MW6 — система для организации wifi mesh для чайников. С возможностью ethernet backhaul, т.е. соединения некоторых блоков друг с другом по проводам, ибо данная коробочка является чуть-ли не самой дешевой wifi mesh (дешевле, по-моему, только их же MW3) и она не имеет третьего выделенного радиотракта для внутренней коммуникации между блоками (как у некоторых дорогих коллег — Netgear Orbi).
В целом, огромной нужды не было, но пара роутеров под OpenWrt не покрывали всех нужных мест.

Кто такой mesh, и зачем он нужен

Mesh — это топология построения сетей, характеризующаяся высокой отказоустойчивостью и динамичностью.
Не буду вдаваться в подробности, так как многие в курсе, а кто нет — можно начать со статьи про Ячеистую топологию на wikipedia.

Основная задача «домашней» wifi mesh сети — это покрыть большую площадь стабильным беспроводным сигналом с бесшовным роумингом.

Бесшовный роуминг можно и на access points и на домашних роутерах включить (например с openwrt — путем замены wpad-mini на wpad и включению 802.11r). А стабильный сигнал на большой площади от пары точек не получить — то пусто, то густо — при этом сильно засоряешь эфир, если повышаешь мощность. Нужно больше точек — несколько точек 5G будет намного эффективнее. Но на обычных access points/routers ты еще будешь думать, как провод к ним подвести, а mesh на то и mesh, чтобы сама себя поддерживать и налаживать связи как при наличии, так и без наличия провода (backhaul).

Вообщем, технология для удобства жизни. Это хорошо.

Завелась система с первого раза, сама настроилась, всё окей. Поиграв с их фичами в приложении (а классической веб-мордочки не предусмотрено, теперь всё только через приложения для телефона и китайские облака…) решил перевести в сеть в режим моста, ибо есть разные устройства уже настроенные как надо и Главный роутер много чего делает.

Сутки всё работало хорошо, потом начал замечать, что то к одному хосту, то к другому нет доступа. В админке OpenWrt в списке выделенных адресов — пара хостов, остальных нет. Сканирую сеть — хосты на месте, только адреса у них не те, что были зафиксированы. Начинаю подозревать — сканирую «главный кубик» MW6 — так и есть, на нем крутится DHCP сервер.

sudo nmap -sU -p 67 —script=dhcp-discover 192.168.5.111

Starting Nmap 7.60 ( https://nmap.org ) at 2019-07-18 20:04 MSK Nmap scan report for _gateway (192.168.5.111) Host is up (0.0027s latency).  PORT   STATE SERVICE 67/udp open  dhcps | dhcp-discover:  |   DHCP Message Type: DHCPACK |   Server Identifier: 192.168.5.111 |   IP Address Lease Time: 23h30m42s |   Subnet Mask: 255.255.255.0 |   Broadcast Address: 192.168.5.255 |   Router: 192.168.5.1 |   Domain Name Server: 192.168.5.1 |_  Domain Name: tendawifi.com MAC Address: 04:95:E6:1A:96:E0 (Tenda Technology,Ltd.Dongguan branch)  Nmap done: 1 IP address (1 host up) scanned in 0.75 seconds

Поддержка у Tenda только де-юро. Де-факто никто ни на что не отвечает. Русская поддержка в контакте хоть и отвечает, но абсолютно не адекватна и не умеет слушать клиентов.

Беглый гуглинг подсказал, что на всякий случай надо бы на Главном роутере поставить dhcp authoritative='1', но это не помогло. И тут я начал думать, как отключить DHCP сервер на этих кубиках. Выделил один кубик для игр, сбросил его настройки и — понеслась.

Сетевые сервисы

Несколько портов открыто, сильно не копал, просто nmap <host>. Подозреваю, что есть и бэкдоры для китайских облаков, но пока их не искал. С ходу ничего полезного не видно. А не с ходу — после подключения к консоли по UART захотел сбросить настройки кубика и выяснил, что после 3 секунд нажатия на reset — запускается telnet сервер.

Вид из LAN

PORT     STATE SERVICE                                                           23/tcp   open  telnet 5500/tcp open  hotline 9000/tcp open  cslistener

Вид из WAN

PORT     STATE  SERVICE 1723/tcp closed pptp

Зайдем-ка в telnet

Ну тут не сильно нам удача улыбалась — всякие стандартные логины/пароли по-перебирал — не подошли. Пробовал root/admin/support/user и пароли из «интернетов» — password, root, toor, admin, support, tenda, 1234, 12345678 и т.д. Пароль от wifi сети тоже пробовал.

Железяки

Кубик открывается легко и непринужденно, шурупы, как обычно, под ножками. Скрытых шурупов нет. Внутри собаки кубика — пустота. Пара плат и пара микро антенн. Ничего интересного, как и везде в 99% случаев.

Повезло с UART — единственный коннектор оказался им. Флэшка прямо по середине. На другой стороне платы ничего нет, кроме радиатора.

Внутренний мир

UART

Разъем J4. Распиновка, начиная с первой ноги: VCC (3.3), TX, RX, GND. Первый нога — которая ближе всего к флешке. Настройки UART тоже угадались с первой попытки — 115200, 8n1.

А вот и долгожданный bootlog. Только для ценителей многих сотен строк.

Booting... init_ram  00000202 M init ddr ok  DRAM Type: DDR2         DRAM frequency: 533MHz         DRAM Size: 128MB JEDEC id 684017, EXT id 0x6840 found BH25Q64 flash vendor: BOHONG BH25Q64, size=8MB, erasesize=64KB, max_speed_hz=55000000Hz auto_mode=0 addr_width=3 erase_opcode=0x000000d8 =>CPU Wake-up interrupt happen! GISR=89000004   ---Realtek RTL8197F boot code at 2018.04.20-10:17+0800 v3.4.11B.9 (999MHz) Mac addr:04-95-e6-1a-96-e0 lan_wan_isolation Initing... config: lan port mask is 0x000000f7 config: wan port mask is 0x000000e8 lan_wan_isolation Initing has been completed. lan_wan_isolation Initing... config: lan port mask is 0x000000f7 config: wan port mask is 0x000000e8 lan_wan_isolation Initing has been completed. wait for upgrage port[0] link:down port[1] link:down port[2] link:down port[3] link:down port[4] link:down irq:0x00008080 Jump to image start=0x80a00000... decompressing kernel: Uncompressing Linux... done, booting the kernel. done decompressing kernel. start address: 0x80466860 Linux version 3.10.90 (root@linux-bkb8) (gcc version 4.4.7 (Realtek MSDK-4.4.7 Build 2001) ) #4 Mon Jul 2 10:57:35 CST 2018 CPU revision is: 00019385 (MIPS 24Kc) Determined physical RAM map:  memory: 08000000 @ 00000000 (usable) Zone ranges:   Normal   [mem 0x00000000-0x07ffffff] Movable zone start for each node Early memory node ranges   node   0: [mem 0x00000000-0x07ffffff] Primary instruction cache 64kB, VIPT, 4-way, linesize 32 bytes. Primary data cache 32kB, 4-way, PIPT, no aliases, linesize 32 bytes Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 8176 Kernel command line:  console=ttyS0,115200 PID hash table entries: 512 (order: -3, 2048 bytes) Dentry cache hash table entries: 16384 (order: 2, 65536 bytes) Inode-cache hash table entries: 8192 (order: 1, 32768 bytes) Writing ErrCtl register=00029693 Readback ErrCtl register=00029693 Memory: 103744k/131072k available (4526k kernel code, 27328k reserved, 2031k data, 224k init, 0k highmem) SLUB: HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1 NR_IRQS:192 Realtek GPIO IRQ init Calibrating delay loop... 666.41 BogoMIPS (lpj=3332096) pid_max: default: 32768 minimum: 301 Mount-cache hash table entries: 2048 NET: Registered protocol family 16 <<<<<Register PCI Controller>>>>> Do MDIO_RESET 40MHz Find PCIE Port, Device:Vender ID=b82210ec Realtek GPIO controller driver init INFO: registering sheipa spi device bio: create slab <bio-0> at 0 INFO: sheipa spi driver register INFO: sheipa spi probe ***spi max freq:100000000 Switching to clocksource MIPS NET: Registered protocol family 2 TCP established hash table entries: 2048 (order: 0, 16384 bytes) TCP bind hash table entries: 2048 (order: -1, 8192 bytes) TCP: Hash tables configured (established 2048 bind 2048) TCP: reno registered UDP hash table entries: 1024 (order: 0, 16384 bytes) UDP-Lite hash table entries: 1024 (order: 0, 16384 bytes) NET: Registered protocol family 1 squashfs: version 4.0 (2009/01/31) Phillip Lougher jffs2: version 2.2. (NAND)  2001-2006 Red Hat, Inc. msgmni has been set to 202 Block layer SCSI generic (bsg) driver version 0.4 loaded (major 254) io scheduler noop registered (default) Serial: 8250/16550 driver, 1 ports, IRQ sharing disabled serial8250: ttyS0 at MMIO 0x18147000 (irq = 17) is a 16550A console [ttyS0] enabled Realtek GPIO to I2C Driver Init... mfi_ioctl_init:565,dev=253,MINOR=0 loop: module loaded m25p80 spi0.0: change speed to 15000000Hz, div 7 JEDEC id 684017 m25p80 spi0.0: found BH25Q64, expected m25p80 flash vendor: BOHONG m25p80 spi0.0: BH25Q64 (8192 Kbytes) (55000000 Hz) m25p80 spi0.0: change speed to 55000000Hz, div 2 Kernel code size:0x1f8012 9 rtkxxpart partitions found on MTD device m25p80 Creating 9 MTD partitions on "m25p80": 0x000000000000-0x000000800000 : "ALL" 0x000000000000-0x000000020000 : "Bootloader" 0x000000020000-0x000000030000 : "CFG" 0x000000030000-0x0000005c0000 : "KernelFS" 0x000000228012-0x0000005c0000 : "RootFS" 0x0000005c0000-0x0000005d0000 : "CFM" 0x0000005d0000-0x0000005e0000 : "CFM_BACKUP" 0x0000005e0000-0x0000007f0000 : "LOG" 0x0000007f0000-0x000000800000 : "ENV" PPP generic driver version 2.4.2 PPP MPPE Compression module registered NET: Registered protocol family 24 PPTP driver version 0.8.5 Realtek WLAN driver - version 1.7 (2015-10-30)(SVN:exported) Adaptivity function - version 9.3.4 Do MDIO_RESET 40MHz Find PCIE Port, Device:Vender ID=b82210ec   found 8822B !!!  halmac_check_platform_api ==========> 12089M HALMAC_MAJOR_VER = 0 HALMAC_PROTOTYPE_VER = 0 HALMAC_MINOR_VER = 0 halmac_init_adapter_88xx ==========> halmac_init_adapter Succss  IS_RTL8822B_SERIES value8 = a  MACHAL_version_init  ####################################################### SKB_BUF_SIZE=8432 MAX_SKB_NUM=1024 #######################################################  MACHAL_version_init RFE TYPE =5  ####################################################### SKB_BUF_SIZE=3032 MAX_SKB_NUM=400 #######################################################  RFE TYPE =5 RFE TYPE =5 RFE TYPE =5 RFE TYPE =5 --- link_loop_init --- mesh_extend_init over... --- hybrid_steering_init --- u32 classifier nf_conntrack version 0.5.0 (1621 buckets, 6484 max) [BM CORE     ][init_online_ip  ,1053]  INFO: online ip data hash table created, size = 199 [BM CORE     ][init_online_ip_procfs,647 ]  INFO: online_ip proc file created ipip: IPv4 over IPv4 tunneling driver gre: GRE over IPv4 demultiplexor driver ip_gre: GRE over IPv4 tunneling driver ip_tables: (C) 2000-2006 Netfilter Core Team TCP: cubic registered NET: Registered protocol family 17 l2tp_core: L2TP core driver, V2.0 l2tp_ppp: PPPoL2TP kernel driver, V2.0 8021q: 802.1Q VLAN Support v1.8 Realtek FastPath:v1.03  Probing RTL819X NIC-kenel stack size order[0]... link_send_msg_timer_func:lan_dev = NULL [Rtl83xx Ethernet Driver][RTL83XX_vlan_set][901]: failed!(0x3) eth0 added. vid=9 Member port 0x2... eth1 added. vid=8 Member port 0x8... [peth0] added, mapping to [eth1]... VFS: Mounted root (squashfs filesystem) readonly on device 31:4. Freeing unused kernel memory: 224K (80668000 - 806a0000) mkdir: can't create directory '/var/run': File exists [BM CORE     ][bm_init         ,857 ]  INFO: bm_init success [BM CORE     ][bm_u2k_info_init,1149]  INFO: bm_u2k_info_init success [MAC FILTER  ][mf_init         ,683 ]  INFO: bm_mac_filter init success  *TBQ* tbq_token_ctrl size:   40 *TBQ* tbq_user size:         68 *TBQ* tbq_user_sched size:   2192 *TBQ* tbq_bucket size:       56 *TBQ* tbq_bucket_sched size: 1796 *TBQ* tbq_flow_track size:   228 *TBQ* tbq_user_track size:   4412 *TBQ* tbq_backlog size:      24 *TBQ* tbq_flow_backlog size: 36 *TBQ* nos_flow_track size:   12 *TBQ* nos_user_track size:   28 *TBQ* nf_conn size:          624 *TBQ* sk_buff size:          232 *TBQ* TBQ_BACKLOG_PACKETS_MAX:  1000000 *TBQ* TBQ_LATENCY_SHIFT_MAX:    10 *TBQ* TBQ_DISABLE_TIMEOUT_MAX:  60 *TBQ* HZ: 100 *TBQ* init_user_tbq_hash_table ok *TBQ* nos_tbq_init() OK Give root password for system maintenance (or type Control-D for normal startup):argv[0] = cfmd cfmd cfms_apmib_init:line(475) Read hw setting header failed!   flash_mib_compress_write DEFAULT_SETTING DONE, __[flash.c-6988]  flash_mib_compress_write CURRENT_SETTING DONE, __[flash.c-7057]  DEFAULT_SETTING hecksum_ok   CURRENT_SETTING hecksum_ok    __[flash.c-7211]setMIB end... setMIB end... setMIB end... setMIB end... setMIB end... setMIB end... setMIB end... setMIB end... setMIB end... setMIB end... setMIB end... setMIB end... setMIB end... setMIB end... setMIB end... setMIB end... setMIB end... setMIB end... setMIB end... setMIB end... setMIB end... setMIB end... setMIB end... setMIB end... setMIB end... setMIB end... setMIB end... setMIB end... setMIB end... argv[0] = timer timer argv[0] = logserver logserver argv[0] = netctrl netctrl prod_change_root_passwd(83) link_send_msg_timer_func:lan_dev = NULL insmod: can't insert '/lib/modules/phy_check.ko': File exists /bin/sh: can't create /proc/sw_nat: Permission denied src/common_hal.c hal_init_bridge device eth0 entered promiscuous mode br0: port 1(eth0) entered listening state br0: port 1(eth0) entered listening state netctrl_main.c,netctrl_init_vlan_ports,1207,: Set br0 to 04:95:e6:1a:96:e0. Sun May  1 00:00:00 UTC 2011 argv[0] = device_list device_list argv[0] = tendaupload tendaupload argv[0] = sh argv[1] = /usr/bin/mesh_op.sh sh  ######## STARTING PROGRAM ######### ######## RECEIVING DATA ######### RTNETLINK answers: Operation not supported check timer start success RTNETLINK answers: No such file or directory [MAC FILTER  ][mf_apply        ,232 ]  INFO: g_mac_filter_enable = disable, mf_default_action = accept [MAC FILTER  ][mf_apply        ,232 ]  INFO: g_mac_filter_enable = disable, mf_default_action = accept Init gsbmac dev success. The ARP attack defence is init v1 successful Interface doesn't accept private ioctl... td_ssid_hide (8BDC): Operation not permitted Interface doesn't accept private ioctl... td_ssid_hide (8BDC): Operation not permitted open /dev/gsbmac failure. open /dev/gsbmac failure. br0: port 1(eth0) entered learning state Kernel:Init attack fence dev success. the ddos ip attack defnence init successful SET_LAN_PARAM_DATA k_data:         lan ip:3232236801         lan mask:4294967040         lan submask:3232236800         lan interface:br0         lan http port:0 set the proceee ture SET_IPOP_FENCE_ATTACK_DATA k_data:         ip options:32512 SET_BAD_PKT_FENCE_ATTACK_DATA k_data:         bad pkt:248 SET_DDOS_FENCE_ATTACK_DATA k_data:         status:7         tcp threshold:1500         udp threshold:1500         icmp threshold:1500 ready___djc___close____guest____wifi_close_guest(4617) djc___close____guest____wifi_close_guest(4623) config changed,CRC:old[3cbf4591],new[3d7bd411] mib_nvram_cfm_commit 1608: write mibvalue success write config to flash......ok ifconfig: SIOCGIFFLAGS: No such device ifconfig: SIOCGIFFLAGS: No such device ifconfig: SIOCGIFFLAGS: No such device ifconfig: SIOCGIFFLAGS: No such device ifconfig: SIOCGIFFLAGS: No such device ifconfig: SIOCGIFFLAGS: No such device ifconfig: SIOCGIFFLAGS: No such device ifconfig: SIOCGIFFLAGS: No such device /bin/sh: wlanapp.sh: not found device wlan1 entered promiscuous mode WlanSupportAbility = 0x3 available channels[US]: 1 2 3 4 5 6 7 8 9 10 11  br0: topology change detected, propagating  br_topology_change_detection, clear br0 fdb ... br_topology_change_detection, clear shortcut cache... br0: port 1(eth0) entered forwarding state MDID is null !!, set default MDID [ODM_software_init]  [97F] Bonding Type 97FS, PKG1 [97F] RFE type 5 PHY paratemters: GPA1+GLNA1 clock 40MHz load efuse ok rom_progress: 0x200006f rom_progress: 0x400006f [GetHwReg88XX][PHY_REG_PG_8197Fmp_Type5] size [GetHwReg88XX][PHY_REG_PG_8197Fmp_Type5] [GetHwReg88XX][rtl8197Ffw] [GetHwReg88XX][rtl8197Ffw size] [97F] Default BB Swing=20  mesh_passphrase_update, before encrypt 65 39 66 66 34 64 32 66 62 65 37 38 30 30 36 30   mesh_passphrase_update, after encrypt 64 34 38 dd 13 2c 3b ad 7b d1 93 8e 8c a8 be 34  br0: port 2(wlan1) entered listening state br0: port 2(wlan1) entered listening state device wlan-msh entered promiscuous mode br0: port 3(wlan-msh) entered listening state br0: port 3(wlan-msh) entered listening state wifi_config_service:4505  ****************** sysconf wlanapp start wlan0 wlan1 wlan0-va0 wlan1-va0  *************** open /proc/gpio: Permission denied open /proc/gpio: Permission denied open /proc/gpio: Permission denied open /proc/gpio: Permission denied Init Wlan application...  FT Daemon v1.0 (Jul  2 2018 10:59:15)  Receive Pathsel daemon pid:1365 [ATM] atm_swq_en on ifconfig: SIOCGIFFLAGS: No such device ifconfig: SIOCGIFFLAGS: No such device ifconfig: SIOCGIFFLAGS: No such device ifconfig: SIOCGIFFLAGS: No such device ifconfig: SIOCGIFFLAGS: No such device ifconfig: SIOCGIFFLAGS: No such device ifconfig: SIOCGIFFLAGS: No such device ifconfig: SIOCGIFFLAGS: No such device /bin/sh: wlanapp.sh: not found !!! adjust 5G 2ndoffset for 8812 !!! br0: port 2(wlan1) entered learning state br0: port 3(wlan-msh) entered disabled state device wlan0 entered promiscuous mode WlanSupportAbility = 0x3 available channels[US]: 36 40 44 48 149 153 157 161 165  MDID is null !!, set default MDID [hard_code_8822_mibs] +++  MAX_RX_BUF_LEN = 8000  [ODM_software_init]  clock 40MHz InitPON OK!!! load efuse ok rom_progress: 0x200006f rom_progress: 0x400006f InitMAC Page0  Init Download FW OK  halmac_init_mac_cfg OK halmac_cfg_rx_aggregation OK halmac_init_mac_cfg OK [GetHwReg88XX][size PHY_REG_PG_8822Bmp_Type6] [GetHwReg88XX][PHY_REG_PG_8822Bmp_Type6] RL6302_MAC_PHY_Parameter_v018_20140708 [set_8822_trx_regs] +++  ******************************** 8822 efuse content 0x3D7 = 0xf4 8822 efuse content 0x3D8 = 0xf5 ********************************  mesh_passphrase_update, before encrypt 65 39 66 66 34 64 32 66 62 65 37 38 30 30 36 30   mesh_passphrase_update, after encrypt 64 34 38 dd 13 2c 3b ad 7b d1 93 8e 8c a8 be 34  br0: port 4(wlan0) entered listening state br0: port 4(wlan0) entered listening state br0: port 3(wlan-msh) entered listening state br0: port 3(wlan-msh) entered listening state wifi_config_service:4505  ****************** sysconf wlanapp start wlan0 wlan1 wlan0-va0 wlan1-va0  *************** open /proc/gpio: Permission denied open /proc/gpio: Permission denied open /proc/gpio: Permission denied open /proc/gpio: Permission denied  FT Daemon v1.0 (Jul  2 2018 10:59:15)  Init Wlan application... Receive Pathsel daemon pid:1502 ==Set ssid close ==Set ssid close br0: topology change detected, propagating  br_topology_change_detection, clear br0 fdb ... br_topology_change_detection, clear shortcut cache... br0: port 2(wlan1) entered forwarding state [ATM] atm_swq_en on wifi_config_service:4505  ****************** sysconf wlanapp start wlan0 wlan1 wlan0-va0 wlan1-va0  *************** open /proc/gpio: Permission denied open /proc/gpio: Permission denied open /proc/gpio: Permission denied open /proc/gpio: Permission denied  FT Daemon v1.0 (Jul  2 2018 10:59:15)  Init Wlan application... Receive Pathsel daemon pid:1538 /bin/sh: et: not found /bin/sh: et: not found /bin/sh: et: not found /bin/sh: et: not found hw_nat_config 113: #####################flags = 1 hw_nat_config 131: ##########enable = 1 hw_nat_config 152: set /proc/hw_nat to 0 cat /proc/hw_nat 0   steering_proc_band_steering_mode_write, local band steering mode Prefer-5GHz check timer start success argv[0] = pann pann argv[0] = gpio_ctrl gpio_ctrl argv[0] = mesh_status_check mesh_status_check argv[0] = network_check network_check User set flags:1 === set mesh_local.registerd = registered(2) br0: port 4(wlan0) entered learning state Phy[0] down Phy[1] down Phy[2] down Phy[3] down Phy[4] down br0: port 3(wlan-msh) entered learning state [arainc][multiWAN is not exit]netctrl_phy_link_status_change(1381) ifconfig: SIOCSIFFLAGS: Cannot assign requested address [netctrl_lan_services_ctrl][354] dhcpcd_lan is already exit!  argv[0] = redis-server argv[1] = /etc_ro/redis.conf redis-server argv[0] = cmdsrv argv[1] = -l argv[2] = tcp://0.0.0.0:12598 argv[3] = -R argv[4] = tcp://127.0.0.1:6379 cmdsrv argv[0] = confsrv confsrv [get_ip_sg][313]ip : 192.168.11.1 [get_ip_sg][313]ip : 192.168.5.1 [1586] 01 May 00:00:11.607 * Max number of open files set to 10032 [1586] 01 May 00:00:11.608 # Warning: 32 bit instance detected but no memory limit set. Setting 3 GB maxmemory limit with 'noeviction' policy now. iptables: Bad rule (does a matching rule exist in that chain?). iptables: Bad rule (does a matching rule exist in that chain?). [dhcps_handle][784]pCurrentCfg is NULL, NewCfgEnable = 1                 _._                                                              _.-``__ ''-._                                                    _.-``    `.  `_.  ''-._           Redis 2.6.17 (00000000/0) 32 bit   .-`` .-```.  ```\/    _.,_ ''-._                                     (    '      ,       .-`  | `,    )     Running in stand alone mode  |`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379  |    `-._   `._    /     _.-'    |     PID: 1586   `-._    `-._  `-./  _.-'    _.-'                                     |`-._`-._    `-.__.-'    _.-'_.-'|                                    |    `-._`-._        _.-'_.-'    |           http://redis.io           `-._    `-._`-.__.-'_.-'    _.-'                                     |`-._`-._    `-.__.-'    _.-'_.-'|                                    |    `-._`-._        _.-'_.-'    |                                     `-._    `-._`-.__.-'_.-'    _.-'                                          `-._    `-.__.-'    _.-'                                                  `-._        _.-'                                                          `-.__.-'                                                 [1586] 01 May 00:00:11.803 # Server started, Redis version 2.6.17 [1586] 01 May 00:00:11.803 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect. [1586] 01 May 00:00:11.803 * The server is now ready to accept connections on port 6379 [1586] 01 May 00:00:11.803 * The server is now ready to accept connections at /tmp/redis.sock Init features[arainc][mpp]mesh_device_features_init(2704) [dhcps_save_config][641]dhcps_save_config end argv[0] = dhcps argv[1] = -C argv[2] = /etc/dhcps.conf argv[3] = -l argv[4] = /etc/dhcps.leases argv[5] = -x argv[6] = /etc/dhcps.pid argv[7] = -k dhcps br0: topology change detected, propagating  br_topology_change_detection, clear br0 fdb ... br_topology_change_detection, clear shortcut cache... br0: port 4(wlan0) entered forwarding state br0: port 1(eth0) entered disabled state Send SIGUSR2 signal from kernel to pathsel, skip for test by Jack br0: topology change detected, propagating  br_topology_change_detection, clear br0 fdb ... br_topology_change_detection, clear shortcut cache... br0: port 3(wlan-msh) entered forwarding state Phy[3] up br0: port 1(eth0) entered listening state br0: port 1(eth0) entered listening state 2011-05-01 00:00:12 [INFO ][uc_api_lib.c,2028][uc_api_lib_init        ] Successfully initialized the api library... sched_boot_set_cfg[62]   rand_num :584   upgrade_shced_timeout start    upgrade_sched_reboot_init_srv(2593) [set_mib 3371]hex format odm[set_mib 4037]set odm,val=0x1e [set_mib 3371]hex format odm[set_mib 4037]set odm,val=0x1e iptables: No chain/target/match by that name. iptables v1.4.4: Couldn't find target `dmz_forward_pre'  Try `iptables -h' or 'iptables --help' for more information. iptables: No chain/target/match by that name. iptables v1.4.4: Couldn't find target `dmz_forward_post'  Try `iptables -h' or 'iptables --help' for more information. iptables: No chain/target/match by that name. iptables: No chain/target/match by that name. iptables: Index of insertion too big. iptables: No chain/target/match by that name. iptables: No chain/target/match by that name. iptables v1.4.4: Couldn't find target `port_forward_pre'  Try `iptables -h' or 'iptables --help' for more information. iptables v1.4.4: Couldn't find target `port_forward_post'  Try `iptables -h' or 'iptables --help' for more information. iptables: No chain/target/match by that name. iptables: No chain/target/match by that name. iptables: No chain/target/match by that name. iptables v1.4.4: Couldn't find target `web_wanadmin'  Try `iptables -h' or 'iptables --help' for more information. iptables: No chain/target/match by that name. [device_list_cmd_sub][1385][luminais] invalid param. iptables: No chain/target/match by that name. iptables v1.4.4: Couldn't find target `web_wanadmin'  Try `iptables -h' or 'iptables --help' for more information. iptables: No chain/target/match by that name. iptables: No chain/target/match by that name. iptables v1.4.4: Couldn't find target `MINIUPNPD'  Try `iptables -h' or 'iptables --help' for more information. iptables: No chain/target/match by that name. miniupnpd.c,871,ver=1.0,osname=Nova,osver=1.0,osurl=http://www.tendacn.com/,manuft=Tenda,descri=Nova br0: port 1(eth0) entered learning state change_opmode: wan_prev_link_flag=1, lan_prev_link_flag=0 br0: port 1(eth0) entered disabled state device eth0 left promiscuous mode br0: port 1(eth0) entered disabled state brctl: bridge br0: Invalid argument set_hw_nat 158: set /proc/hw_nat to 1 /proc/hw_nat now is 1  [Rtl83xx Ethernet Driver][RTL83XX_vlan_set][901]: failed!(0x3) RTNETLINK answers: No such file or directory argv[0] = ucloud argv[1] = -l argv[2] = 4 ucloud killall: telnet_ate_monitor: no process killed Phy[3] down 2011-05-01 00:00:16 [INFO ][uc_api_lib.c,1938][ucloud_event_accept2   ] accept ucloud session 16 2011-05-01 00:00:16 [INFO ][uc_api_lib.c,1952][ucloud_event_accept2   ] traversal notify info 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_CLOUD_INFO_MESH_NODE_A[14] in module: M_CLOUD_INFO[8]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_CLOUD_INFO_DEV_UPLOAD_STATU[20] in module: M_CLOUD_INFO[8]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_CLOUD_INFO_DEV_UPLOAD_DEVIC[18] in module: M_CLOUD_INFO[8]... 2011-05-01 00:00:16 =Set ssid open m[INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_CL==Set ssid open OUD_INFO_DEV_MARK_LIST_A[21] in module: M_CLOUD_INFO[8]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_CLOUD_INFO_DEV_CONFIG_TIME_[23] in module: M_CLOUD_INFO[8]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_CLOUD_INFO_DEV_CONFIG_A[25] in module: M_CLOUD_INFO[8]... enable cloud info OK init_device_attr_desc(2680) get_mesh_info(2614) get_mesh_info(2650) 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_CLOUD_INFO_MESH_SET[11] in module: M_CLOUD_INFO[8]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_CLOUD_INFO_CHECK_MEMORY[0] in module: M_CLOUD_INFO[8]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_CLOUD_INFO_BEGIN_UPGRADE[4] in module: M_CLOUD_INFO[8]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c,1955][ucloud_event_accept2   ] Init Modules 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: MESH_WAN_SET[1] in module: MESH_WAN[18]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: MESH_WAN_GET[2] in module: MESH_WAN[18]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_MESH_WAN_DETECT[3] in module: M_MESH_WAN[18]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_MESH_WAN_STATUS[0] in module: M_MESH_WAN[18]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_MESH_WAN_DIAG[4] in module: M_MESH_WAN[18]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_MESH_WAN_LINEUP_GET[7] in module: M_MESH_WAN[18]... 2011-05-01 Receive Pathsel daemon pid:2004 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_MESH_WAN_TRAFFIC[8] in module: M_MESH_WAN[18]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_MESH_WLAN_GET[1] in module: M_MESH_WLAN[19]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_MESH_WLAN_SET[0] in module: M_MESH_WLAN[19]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_MESH_WLAN_GET[3] in module: M_MESH_WLAN[19]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_MESH_WLAN_SET[2] in module: M_MESH_WLAN[19]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_MESH_WLAN_ROAMING_GET[4] in module: M_MESH_WLAN[19]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_MESH_WLAN_ROAMING_SET[5] in module: M_MESH_WLAN[19]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_MESH_BASIC_SUILT[0] in module: M_MESH_BASIC[16]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_MESH_BASIC_TZ_SET[1] in module: M_MESH_BASIC[16]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_MESH_BASIC_TIME_SET[2] in module: M_MESH_BASIC[16]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_MESH_BASIC_LANG_SET[3] in module: M_MESH_BASIC[16]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_MESH_BASIC_FAST_DONE[4] in module: M_MESH_BASIC[16]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_MESH_BASIC_GET_MESH_ID[5] in module: M_MESH_BASIC[16]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_MESH_BASIC_UPLOAD_LOG[6] in module: M_MESH_BASIC[16]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_MESH_NODE_BROWS[0] in module: M_MESH_NODE[17]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_MESH_NODE_ADD[1] in module: M_MESH_NODE[17]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_MESH_NODE_DEL[2] in module: M_MESH_NODE[17]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_MESH_NODE_SET_LOCATION[3] in module: M_MESH_NODE[17]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_MESH_NODE_SET_LED[4] in module: M_MESH_NODE[17]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_MESH_NODE_QUERY_RSLT[5] in module: M_MESH_NODE[17]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_MESH_NODE_MULTI_UPGRADE_STA[6] in module: M_MESH_NODE[17]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_MESH_NODE_MANUAL_ADD[7] in module: M_MESH_NODE[17]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_MESH_HOSTS_GET[0] in module: M_MESH_HOSTS[20]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_MESH_HOSTS_MARK[1] in module: M_MESH_HOSTS[20]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_MESH_HOSTS_GET_REMARK[2] in module: M_MESH_HOSTS[20]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_MESH_MF_GET[0] in module: M_MESH_MACFILTER[21]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_MESH_MF_SET[1] in module: M_MESH_MACFILTER[21]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_MESH_FAMILY_GET_TMGRP[0] in module: M_MESH_FAMILY[22]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_MESH_FAMILY_SET_TMGRP[1] in module: M_MESH_FAMILY[22]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_MESH_FAMILY_GET_USRGRP[2] in module: M_MESH_FAMILY[22]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_MESH_FAMILY_SET_USRGRP[3] in module: M_MESH_FAMILY[22]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_MESH_FAMILY_GET_FMLYGRP[4] in module: M_MESH_FAMILY[22]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_MESH_FAMILY_SET_FMLYGRP[5] in module: M_MESH_FAMILY[22]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_MESH_ADV_PORTFWD_GET[0] in module: M_MESH_ADVANCE[23]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_MESH_ADV_PORTFWD_SET[1] in module: M_MESH_ADVANCE[23]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_MESH_ADV_UPNP_GET[2] in module: M_MESH_ADVANCE[23]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_MESH_ADV_UPNP_SET[3] in module: M_MESH_ADVANCE[23]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_MESH_ADV_MAINT_GET[4] in module: M_MESH_ADVANCE[23]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_MESH_ADV_MAINT_SET[5] in module: M_MESH_ADVANCE[23]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_MESH_ADV_DHCPS_GET[6] in module: M_MESH_ADVANCE[23]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_MESH_ADV_DHCPS_SET[7] in module: M_MESH_ADVANCE[23]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_MESH_ADV_QOS_GET[8] in module: M_MESH_ADVANCE[23]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_MESH_ADV_QOS_SET[9] in module: M_MESH_ADVANCE[23]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_MESH_ADV_DEV_ASSISTANT_GET[10] in module: M_MESH_ADVANCE[23]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_MESH_ADV_DEV_ASSISTANT_SET[11] in module: M_MESH_ADVANCE[23]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_MESH_ADV_SHAREDACC_GET[12] in module: M_MESH_ADVANCE[23]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_MESH_ADV_HIGH_DEVICE_GET[15] in module: M_MESH_ADVANCE[23]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_MESH_ADV_HIGH_DEVICE_SET[16] in module: M_MESH_ADVANCE[23]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_CLOUD_VERSION_Q[24] in module: M_CLOUD[3]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_CLOUD_INFO_CLEAR_ACC_ACK[9] in module: M_CLOUD_INFO[8]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_CLOUD_INFO_ACCOUNT_INFO_A[16] in module: M_CLOUD_INFO[8]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_MESH_MNGMT_GET_STA[0] in module: M_MESH_AUTH[24]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_MESH_MNGMT_LOGIN[1] in module: M_MESH_AUTH[24]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_SYS_BASIC_INFO_GET[0] in module: M_SYS[1]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_CATEGORY_MESH[1] in module: M_CATEGORY[15]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_COMMON_SUCCESS[0] in module: M_COMMON[0]... 2011-05-01 00:00:16 [INFO ][uc_api_lib.c, 344][uc_api_lib_cmd_register] Successfully registered command: CMD_COMMON_FAILURE[1] in module: M_COMMON[0]... argv[0] = sntp argv[1] = 1 argv[2] = 10800 argv[3] = 43200 sntp main,297,sntp_en =1,tz_offset_sec=10800,checktime=43200 wifi_config_service:4505  ****************** sysconf wlanapp start wlan0 wlan1 wlan0-va0 wlan1-va0  *************** open /proc/gpio: Permission denied open /proc/gpio: Permission denied open /proc/gpio: Permission denied open /proc/gpio: Permission denied Init Wlan application...  FT Daemon v1.0 (Jul  2 2018 10:59:15)  change_opmode: sleep 1s for NIC restart. change_opmode: sleep 2s for NIC restart. wifi_config_service:4505  ****************** sysconf wlanapp start wlan0 wlan1 wlan0-va0 wlan1-va0  *************** open /proc/gpio: Permission denied open /proc/gpio: Permission denied open /proc/gpio: Permission denied open /proc/gpio: Permission denied  FT Daemon v1.0 (Jul  2 2018 10:59:15)  Init Wlan application... Receive Pathsel daemon pid:2078 [arainc][multiWAN is not exit]netctrl_phy_link_status_change(1381) change_opmode: sleep 3s for NIC restart. device eth0 entered promiscuous mode br0: port 1(eth0) entered listening state br0: port 1(eth0) entered listening state [arainc][multiWAN is not exit]netctrl_phy_link_status_change(1381) change_opmode: sleep 1s for port reverted. ###fd failed to recv packet!### ##### NO SERVER FOUND! ##### br0: port 1(eth0) entered learning state br0: port 2(wlan1) entered disabled state change_opmode: sleep 2s for port reverted. ifconfig: SIOCGIFFLAGS: No such device ifconfig: SIOCGIFFLAGS: No such device ifconfig: SIOCGIFFLAGS: No such device ifconfig: SIOCGIFFLAGS: No such device ifconfig: SIOCGIFFLAGS: No such device ifconfig: SIOCGIFFLAGS: No such device ifconfig: SIOCGIFFLAGS: No such device ifconfig: SIOCGIFFLAGS: No such device /bin/sh: wlanapp.sh: not found br0: port 3(wlan-msh) entered disabled state WlanSupportAbility = 0x3 available channels[US]: 1 2 3 4 5 6 7 8 9 10 11  [ODM_software_init]  [97F] Bonding Type 97FS, PKG1 [97F] RFE type 5 PHY paratemters: GPA1+GLNA1 clock 40MHz load efuse ok rom_progress: 0x200006f rom_progress: 0x400006f [GetHwReg88XX][PHY_REG_PG_8197Fmp_Type5] size [GetHwReg88XX][PHY_REG_PG_8197Fmp_Type5] [GetHwReg88XX][rtl8197Ffw] [GetHwReg88XX][rtl8197Ffw size] [97F] Default BB Swing=20  mesh_passphrase_update, before encrypt 65 39 66 66 34 64 32 66 62 65 37 38 30 30 36 30   mesh_passphrase_update, after encrypt 64 34 38 dd 13 2c 3b ad 7b d1 93 8e 8c a8 be 34  br0: port 2(wlan1) entered listening state br0: port 2(wlan1) entered listening state br0: port 3(wlan-msh) entered listening state br0: port 3(wlan-msh) entered listening state wifi_config_service:4505  change_opmode: sleep 3s for port reverted. ****************** sysconf wlanapp start wlan0 wlan1 wlan0-va0 wlan1-va0  *************** open /proc/gpio: Permission denied open /proc/gpio: Permission denied open /proc/gpio: Permission denied open /proc/gpio: Permission denied Init Wlan application...  FT Daemon v1.0 (Jul  2 2018 10:59:15)  Receive Pathsel daemon pid:2394 [ATM] atm_swq_en on br0: topology change detected, propagating  br_topology_change_detection, clear br0 fdb ... br_topology_change_detection, clear shortcut cache... br0: port 1(eth0) entered forwarding state change_opmode: sleep 4s for port reverted. br0: port 2(wlan1) entered learning state br0: port 3(wlan-msh) entered learning state change_opmode: sleep 5s for port reverted. change_opmode: sleep 6s for port reverted. br0: topology change detected, propagating  br_topology_change_detection, clear br0 fdb ... br_topology_change_detection, clear shortcut cache... br0: port 2(wlan1) entered forwarding state Send SIGUSR2 signal from kernel to pathsel, skip for test by Jack br0: topology change detected, propagating  br_topology_change_detection, clear br0 fdb ... br_topology_change_detection, clear shortcut cache... br0: port 3(wlan-msh) entered forwarding state change_opmode: sleep 7s for port reverted. change_opmode: sleep 8s for port reverted. change_opmode: sleep 9s for port reverted. change_opmode: sleep 10s for port reverted. change_opmode: sleep 11s for port reverted. Phy[3] up [arainc][multiWAN is not exit]netctrl_phy_link_status_change(1381) change_opmode: sleep 12s for port reverted. change_opmode: NIC restart finished.(WAN:1,LAN:0) src/prod_common_rtl_fn_delete: failed del route from rtl865x! hal.c,add_local_route_to_switch,179: config (192.168.5.0,255.255.255.0,br0) to the Realtek ASIC L3 Routing Table [hw_nat_msg_handle][245]var->op 3 [set_hw_nat_by_guest_network][76]guest network is close! eth1 has been deleted from br0! hw_nat_config 113: #####################flags = 1 hw_nat_config 131: ##########enable = 1 hw_nat_config 152: set /proc/hw_nat to 0 cat /proc/hw_nat wandial_handle(231) 0   [arainc][ctrl_op = 1]netctrl_moudle_multiwan_handle(22) argv[0] = multiWAN multiWAN multiWAN -> multiwan_bad_sig_entry [18]...ct = 9 open:: No such file or directory multiWAN -> multiwan_bad_sig_entry [18]...ct = 8 iptables: No chain/target/match by that name. multiWAN -> multiwan_bad_sig_entry [18]...ct = 7 iptables: No chain/target/match by that name. multiWAN -> multiwan_bad_sig_entry [18]...ct = 6 multiWAN -> multiwan_bad_sig_entry [18]...ct = 5 multiWAN -> multiwan_bad_sig_entry [18]...ct = 4 multiWAN -> multiwan_bad_sig_entry [18]...ct = 3 iptables: No chain/target/match by that name. multiWAN -> multiwan_bad_sig_entry [18]...ct = 2 multiWAN -> multiwan_bad_sig_entry [18]...ct = 1 multiWAN -> multiwan_bad_sig_entry [18]...ct = 0 iptables: No chain/target/match by that name. iptables: No chain/target/match by that name. argv[0] = dhcpcd_wan1 argv[1] = -c argv[2] = /etc/wan1.ini argv[3] = -m argv[4] = 1 argv[5] = eth1 argv[6] = -h argv[7] = NOVA-0495e61a96e0 argv[8] = -x argv[9] = /etc/dhcpc-wan-up1.sh dhcpcd_wan1 program_name = dhcpcd_lan killall: dhcpcd_lan: no process killed [multiwan_msg_handle][2849]recv_info->SendPid = 7, recv_info->SendMid = 7, recv_info->RecvPid = 5, recv_info->RecvMid = 5 ganda_debug--[igmp_start]107 IGMP UP!!! iptables: Bad rule (does a matching rule exist in that chain?). iptables: Bad rule (does a matching rule exist in that chain?). *TBQ* disabling tbq ... *TBQ* tbq enqueue handlers is disabled igmpproxy, Version 0.1 beta2, Build 170904  Copyright 2005 by Johnny Egeland <j*TBQ* notify disable done in timer func ohnny@rlo.org> *TBQ* tbq backlog is cleared Distributed unde*TBQ* tbq disabled r the GNU GENERAL PUBLIC LICENSE, Version 2 - check GPL.txt  update_hwnat_setting 383:/proc/hw_nat now is 0  route: SIOCDELRT: No such process [multiwan_set_route_single_wan][1308][luminais] add_default_route_success [getAllWanDns][125]wan1.manual.dns.en = 0 [getAllWanDns][187]dns_buf =  -s 192.168.3.1 argv[0] = dnrd argv[1] = -t argv[2] = 3 argv[3] = -M argv[4] = 600 argv[5] = --cache=off argv[6] = -b argv[7] = -R argv[8] = /etc/dnrd argv[9] = -r argv[10] = 3 argv[11] = -s argv[12] = 192.168.3.1 dnrd [lan_wan_ip_conflict_check][707][luminais] wan : 192.168.3.140/255.255.255.0 Notice: caching turned off [lan_wan_ip_conflict_check][722][luminais] br0 : 192.168.5.1/255.255.255.0 [multiwan_msg_handle][2849]recv_info->SendPid = 4, recv_info->SendMid = 4, recv_info->RecvPid = 5, recv_info->RecvMid = 5 open /dev/flow failed:: No such file or directory iptables: No chain/target/match by that name. iptables v1.4.4: Couldn't find target `icmp_access'  Try `iptables -h' or 'iptables --help' for more information. *TBQ* tbq is not running *TBQ* config size: 278 *TBQ* Operation not set *TBQ* wanid=ffffffff set *TBQ* config.Rules[n].IpIncluded not set *TBQ* config.Rules[n].UserIncluded not set *TBQ* config.Rules[n].AppIncluded not set *TBQ* MaxBacklogPackets set to: 9999 *TBQ* reloading tbq ... *TBQ* tbq reloaded *TBQ* ------------- TBQ CONFIG (rule count: 1) ------------- *TBQ* ~~~~~~~~~ TBQ RULE [UI-GLOBAL] ~~~~~~~~~ *TBQ* global out tokens_per_jiffy: 1280000 *TBQ* user   out tokens_per_jiffy: 1280000 *TBQ* global in tokens_per_jiffy: 1280000 *TBQ* user   in tokens_per_jiffy: 1280000 *TBQ* max_backlog_packets:  9999 *TBQ* latency_shift:        7 *TBQ* disable_timeout:      2 *TBQ* ------------------------------------------ *TBQ* tbq enabled killall: xl2tpd-server: no process killed iptables: No chain/target/match by that name. iptables: Chain already exists. iptables: Chain already exists. iptables: No chain/target/match by that name. iptables v1.4.4: Couldn't find target `web_wanadmin'  Try `iptables -h' or 'iptables --help' for more information. iptables: No chain/target/match by that name. iptables: No chain/target/match by that name. iptables v1.4.4: Couldn't find target `web_wanadmin'  Try `iptables -h' or 'iptables --help' for more information. iptables: No chain/target/match by that name. miniupnpd.c,871,ver=1.0,osname=Nova,osver=1.0,osurl=http://www.tendacn.com/,manuft=Tenda,descri=Nova [hw_nat_msg_handle][245]var->op 2 [set_hw_nat_by_guest_network][76]guest network is close! hw_nat_config 113: #####################flags = 0 hw_nat_config 131: ##########enable = 0 [fill_cloud_info_device_lists_rate][2600][luminais] NULL == g_ip_info cat /proc/hw_nat [mib_load_manage][472][luminais] GetBasicInfo [0] 0   [mib_save_manage][532][luminais] AccoutACK [0] dev_mark_list_a(72) [dev_mark_list_a][75] [upload_local_diff_remark_to_cloud][2270][luminais] all client remark same with cloud. [mesh_node_a][242] [cloud_mesh_node_handle][3977] [save_mesh_node_group_conf][387][kg] groupsn = 181285920113001948 not need to write flash,crc:[3d7bd411] commit cfm failed or not need write flash not need to write flash,crc:[3d7bd411] commit cfm failed or not need write flash   s_time :1562925999991  config_time :1562925999991    local_time:1562925999991     telnet_ate_monitor_recv(166) telnet_ate_monitor_recv(166)  [hw_nat_msg_handle][245]var->op 1 [set_hw_nat_by_guest_network][76]guest network is close! hw_nat_config 113: #####################flags = 1 hw_nat_config 131: ##########enable = 0 cat /proc/hw_nat 0   Normal startupGive root password for system maintenance (or type Control-D for normal startup): 

Консоль приглашает зайти, но без пароля рута не пускает.

Flash

Китайская на 146% SPI flash BOHONG BH25Q64 на 8 Мб. Datasheet

Прошивка, то бишь firmware

Прошивку скачать с просторов интернета не удалось. Приложение на телефоне само скачивает прошивки из китайского Tenda облака, причем по своему протоколу, как выяснилось позже. Мои кубики имеют последнюю прошивку, по-этому вынюхать, откуда скачивается прошивка, не удалось.

Давайте просто снимем дамп с флешки

Сначала попробовал надеть сверху на чип клещи и считать прошивку — но, как и ожидалось, у меня этого не получилось, т.к. запитывая флешку, запустился процессор и пошло поехало. Резать дорожки не хотелось, поэтому решил выпаять. Огородив окрестности Онежского озера окаянного отпрыска китайской промышленности каптоновым скотчем — подогрел феном и выпаял зверушку по-македонски — двумя паяльниками. Ну и хочется динамичности в процессе смены прошивок — подпаял хвостики для кроватки.

Так удобнее перепрошивать флешку

Чем бы снять дамп?

Флешки я читаю раз в пять лет, надобности нет, а соответственно — и программаторов для них. В закромах нашел платку FTDI FT2232H, которой я пользовался для отладки ESP32 через JTAG + OpenOCD. Оказалось, она много чего умеет. В том числе и SPI в режиме мастера. Нагуглил на нее даташит и записал распиновку при подключении к первому каналу (порту):

FT2232H Function Нога на флешке
ADBUS0 SCK 6
ADBUS1 MOSI 5
ADBUS2 MISO 2
ADBUS3 CS 1

Оставшиеся ножки флешки 4 — GND, 8, 3 и 7 — VCC 3.3v.

Подключение к FT2232H

Flashrom

Параллельно поиску железяк в закромах нагуглил flashrom — популярная утилитка для работы с флешками.

Запускаем…

$ flashrom -p ft2232_spi:type=2232H,port=A

… и, вообщем, смотрим в книгу — видим фигу.

$ flashrom v0.9.9-r1954 on Linux 4.18.0-25-generic (x86_64)

flashrom is free software, get the source code at https://flashrom.org   Calibrating delay loop... OK. Found Generic flash chip "unknown SPI chip (RDID)" (0 kB, SPI) on ft2232_spi. === This flash part has status NOT WORKING for operations: PROBE READ ERASE WRITE  The test status of this chip may have been updated in the latest development  version of flashrom. If you are running the latest development version, please email a report to flashrom@flashrom.org if any of the above operations work correctly for you with this flash chip. Please include the flashrom log  file for all operations you tested (see the man page for details), and mention  which mainboard or programmer you tested in the subject line. Thanks for your help! No operations were specified.

К сожалению, флешка черезчур китайская, софтинка её понимать отказалась, а может ли она работать в каком-то «стандартном» или «generic» режиме я не понял.

Ардуины спешат на помощь. Ну и esp8266 с ними.

Опять пошел гуглить. Нагуглил древнюю поделку доброго человека с сайта Технохрень. Комплект из скетча для ардуины и приложения на .NET.

Поразмыслив, что для ардуины придется городить согласование уровней 3.3в и 5в — взял из закромов платку NodeMCU на esp8266. Она на 3.3в.
Скетч запустился без проблем, правда я никак не мог флешку прочитать — после пары научных тыков преподключил флешку ко второму SPI порту, который называется HSPI и выведен на ноги GPIO 12..14 согласно официальной документации.

  • NB Надо сказать, что flashrom еще умеет работать с программатором serprog, в который собственно можно превратить любую 8-битную AVRку, включая ардуины. Но, к сожалению, быстрый гуглинг порта для esp8266 не дал результатов.

esp8266 HSPI

Дайте нормальную флешку!

Вообщем, чтобы не париться с китайской флешкой, в небезызвестном своими ценовыми политиками магазине имени двух бурундуков приобрел за огромные деньги в 110 рублей (2 USD) нормальную флешку Winbond W25Q64FV. Куда тут же залил считанный дамп и воткнул в кубик.

$ flashrom -p ft2232_spi:type=2232H,port=A -w all.bin

Tenda флешку подхватила и запустилась, как ни в чем не бывало. (Хотя, по-моему, она разок перезагрузилась, переписав что-то в конфиге/облаке. Не заметил что именно).

А ну-ка, давай-ка

В прошивке что-то есть. По крайней мере, binwalk нашел всякого. Как я понял — достаточно стандартно для таких железяк.
Попробуем раскопать, что-нибудь исправить и закопать обратно.

$ binwalk all.bin

DECIMAL       HEXADECIMAL     DESCRIPTION -------------------------------------------------------------------------------- 35096         0x8918          CRC32 polynomial table, little endian 36192         0x8D60          gzip compressed data, maximum compression, from Unix, last modified: 2018-04-20 02:17:42 206872        0x32818         LZMA compressed data, properties: 0x5D, dictionary size: 8388608 bytes, uncompressed size: 6890804 bytes 2261010       0x228012        Squashfs filesystem, little endian, version 4.0, compression:xz, size: 3071844 bytes, 378 inodes, blocksize: 131072 bytes, created: 1902-05-30 15:13:04 6160384       0x5E0000        JFFS2 filesystem, little endian

Сразу распаковывать не стал. Еще первый раз в bootlog-е видел, что мелькала разбивка флешки на разделы — сначала разбил командой dd на соответствующие куски, а потом уже играл с binwalk.

bootlog : mtd partitions

flash vendor: BOHONG m25p80 spi0.0: BH25Q64 (8192 Kbytes) (55000000 Hz) m25p80 spi0.0: change speed to 55000000Hz, div 2 Kernel code size:0x1f8012 9 rtkxxpart partitions found on MTD device m25p80 Creating 9 MTD partitions on "m25p80": 0x000000000000-0x000000800000 : "ALL" 0x000000000000-0x000000020000 : "Bootloader" 0x000000020000-0x000000030000 : "CFG" 0x000000030000-0x0000005c0000 : "KernelFS" 0x000000228012-0x0000005c0000 : "RootFS" 0x0000005c0000-0x0000005d0000 : "CFM" 0x0000005d0000-0x0000005e0000 : "CFM_BACKUP" 0x0000005e0000-0x0000007f0000 : "LOG" 0x0000007f0000-0x000000800000 : "ENV"

Пример вырезания RootFS из файла прошивки all.bin:

$ dd if=all.bin of=RootFS.bin bs=1 skip=$((0x228012)) count=$((0x5c0000-0x228012))

Я не специалист, но мне кажется странным, что согласно разметке раздел RootFS находится внутри KernelFS.

Кроме того, устройство ядра для меня загадка, поэтому его трогать не стал.

Весть процесс загрузки, как я понял, почти прямолинеен:

  • сначала процессор отображает флешку к себе в память,
  • запускает bootloader,
  • bootloader проверяет, не хочет ли кто-то по TFTP загрузить новую прошивку,
  • после чего он грузит уже ядро.

RootFS

Распаковать файловую систему элементарно — unsquashfs RootFS.bin. В результате работы появляется папка squashfs-root с деревом папок/файлов.

  • Тут уже есть, что посмотреть! — подумал я.

cat /etc_ro/passwd

root:$1$nalENqL8$jnRFwb1x5S.ygN.3nwTbG1:0:0:root:/:/bin/sh

cat /etc_ro/shadow

root:$1$OVhtCyFa$7tISyKW1KGssHAQj1vI3i1:14319::::::

cat /etc_ro/inittab

::sysinit:/etc_ro/init.d/rcS ttyS0::respawn:/sbin/sulogin ::ctrlaltdel:/bin/umount -a -r ::shutdown:/usr/sbin/usb led_off

В `/etc_ro/fstab` ничего интересного.

proc            /proc           proc    defaults 0 0 #none            /var            ramfs   defaults 0 0 none            /tmp            ramfs   defaults 0 0 mdev            /dev            ramfs   defaults 0 0 none            /sys            sysfs   defaults 0 0

Впрочем, ничего интересного я не нашел и в `/etc_ro/init.d/rcS`.

#! /bin/sh  PATH=/sbin:/bin:/usr/sbin:/usr/bin/ export PATH  mount -t ramfs none /var/  mkdir -p /var/etc mkdir -p /var/media mkdir -p /var/webroot mkdir -p /var/etc/iproute mkdir -p /var/run mkdir -p /var/debug  cp -rf /etc_ro/* /etc/ cp -rf /webroot_ro/* /webroot/ mkdir -p /var/etc/upan mount -a  mount -t ramfs /dev mkdir /dev/pts mount -t devpts devpts /dev/pts mount -t tmpfs none /var/etc/upan -o size=2M mdev -s mkdir /var/run echo 1 > /proc/sys/vm/panic_on_oom echo 1 > /proc/sys/kernel/panic_on_oops  echo '/sbin/mdev' > /proc/sys/kernel/hotplug #echo 'sd[a-z][0-9] 0:0 0660 @/usr/sbin/autoUsb.sh $MDEV' >> /etc/mdev.conf #echo 'sd[a-z] 0:0 0660 $/usr/sbin/DelUsb.sh $MDEV' >> /etc/mdev.conf #echo 'lp[0-9] 0:0 0660 */usr/sbin/IppPrint.sh'>> /etc/mdev.conf #wds rule start echo 'wds*.* 0:0 0660 */etc/wds.sh $ACTION $INTERFACE' > /etc/mdev.conf #wsd rule end echo 'sd[a-z][0-9] 0:0 0660 @/usr/sbin/usb_up.sh $MDEV $DEVPATH' >> /etc/mdev.conf echo '-sd[a-z] 0:0 0660 $/usr/sbin/usb_down.sh $MDEV $DEVPATH'>> /etc/mdev.conf echo 'sd[a-z] 0:0 0660 @/usr/sbin/usb_up.sh $MDEV $DEVPATH'>> /etc/mdev.conf echo '.* 0:0 0660 */usr/sbin/IppPrint.sh $ACTION $INTERFACE'>> /etc/mdev.conf mkdir -p /var/ppp  insmod /lib/modules/dhcp_options.ko #insmod /lib/modules/gpio.ko insmod /lib/modules/phy_check.ko #insmod /lib/modules/fastnat.ko  insmod /lib/modules/bm.ko #insmod /lib/modules/ai.ko  insmod /lib/modules/mac_filter.ko  #insmod /lib/modules/ip_mac_bind.ko #insmod /lib/modules/privilege_ip.ko insmod /lib/modules/nos.ko #insmod /lib/modules/url_filter.ko #insmod /lib/modules/loadbalance.ko #insmod /lib/modules/app_filter.ko #insmod /lib/modules/port_filter.ko #insmod /lib/modules/arp_fence.ko #insmod /lib/modules/ddos_ip_fence.ko #/etc/gpio_conf echo "enable 0 interval 0" >/proc/watchdog_cmd chmod +x /etc/mdev.conf mkdir -p /tmp/log mkdir -p /tmp/log/crash mkdir -p /tmp/log_print  ln -sf /proc/port1 /var/port1 ln -sf /proc/port3 /var/port0  echo 'kern.* /tmp/log/kernel.log' >>  /etc/syslog.conf echo '*.* /tmp/log_print/message.txt' >>  /etc/syslog.conf  klogd -n & syslogd -f /var/etc/syslog.conf -s 50 &  monitor & sh /usr/bin/ugw_watchdog.sh 2>/tmp/log_print/ugw_watchdog.log& #sh /usr/bin/mesh_op.sh > /dev/null &

Юзеров не много, ttyS0 можно было бы и не на /sbin/sulogin натравливать, а на /bin/login -f root или /bin/sh.

Вторая наивная попытка войти

Попробуем поправить /etc_ro/inittab. Заменил ttyS0::respawn:/sbin/sulogin на ttyS0::respawn:/bin/login -f root.

Запаковал обратно squashfs с помощью mksquashfs — файл стал в 1.5 раза больше и перестал влезать в раздел. Заметил, что оригинальный файл был пожат алгоритмом xz, а утилита по-умолчанию использует lzma. Переделал файл с нужным алгоритмом компресии — все стало ок. Подсмотрев в содержимое оригинального дампа раздела RootFS добил свой новый файл до размера раздела байтом 0xff. С помощью dd скопировал новый раздел на место старого. Записал всё на флешку. Потираю ручки, включаю кубик…

Booting…

init_ram  00000202 M init ddr ok  DRAM Type: DDR2         DRAM frequency: 533MHz         DRAM Size: 128MB JEDEC id EF4017, EXT id 0x0000 found w25q64 flash vendor: Winbond w25q64, size=8MB, erasesize=64KB, max_speed_hz=29000000Hz auto_mode=0 addr_width=3 erase_opcode=0x000000d8 =>CPU Wake-up interrupt happen! GISR=89000004   ---Realtek RTL8197F boot code at 2018.04.20-10:17+0800 v3.4.11B.9 (999MHz) Mac addr:04-95-e6-1a-96-e0 lan_wan_isolation Initing... config: lan port mask is 0x000000f7 config: wan port mask is 0x000000e8 lan_wan_isolation Initing has been completed. lan_wan_isolation Initing... config: lan port mask is 0x000000f7 config: wan port mask is 0x000000e8 lan_wan_isolation Initing has been completed. wait for upgrage port[0] link:down port[1] link:down port[2] link:down port[3] link:down port[4] link:down irq:0x00008080 rootfs checksum error at 00228012! <RealTek>

Какой мощный фейл! Как я вообще мог не подумать про CRC.

Смотрю еще раз binwalk — bootloader не UBoot, гуглинг подсказывает, что RealTek — ребята скрытные. В общем доступе описания нет, кроме того, под каждый девайс свои сигнатуры призывают делать, чтобы неповадно реверсить было… Эх.

Для UBoot и ряда других случаев может помочь древний заброшенный проект firmware-mod-kit, либо есть гордый потомок — наикрутейший Firmware Analysis Toolkit

Погуглил по темным закоулкам интернета — нашел относительно свежий RealTek SDK года 2015-го. Архив на 600 Мб. Одним глазом поглядел на процесс построения финального образа прошивки и расчет CRC — плюнул и закрыл. Пока что жалко мозг. И время. Может быть потом как-нибудь.

Еще попыточка

Конечно же, я с первого раза заметил, что при загрузке кубик выдает подозрительную надпись в логе:

argv[0] = netctrl netctrl prod_change_root_passwd(83)

Запускается процесс netctrl и меняет пароль.

Ну давайте поиграем. Вспомнил, как 20 лет назад писал софт по ZX Spectrum на ассемблере и ломал игрушки, чтобы жизней было побольше и бесконечные патроны.
Больше к ассемблеру не притрагивался, не считая того факта, что на 3-4 года позже благодаря ему я попал на первую работу. Фиксал KDE под FreeBSD драйвера для виндовского setup-загрузчика.

Берем IDA PRO в долг у приятеля.

Куда же посмотреть сначала?

Наверное надо найти, где же выводится данная надпись. Ищем текст prod_change_root_passwd по файлам — в результатах много исполняемых файлов, включая тот самый /bin/netctrl, а также одна библиотека /lib/libcommonprod.so. Нам повезло — судя по всему и функция и текст вывода на экран совпадают, а сама реализация — в файле библиотеки.

Вспомнила бабка первый поцелуй

Запускаем IDA PRO, который я вижу первый раз в жизни. Как и MIPS ассемблер.

Открываем /bin/netctrl. Система сразу любезно открыла нам функцию main. Ничего не понятно, но, судя по всему, вначале очищаются буферы и инициализируются локальные переменные. А потом, скорее всего, из конфига считывается параметр sys.role и на основе его значения программа либо засыпает, либо… вызывает внешнюю функцию с тем самым подозрительным названием. Параметров вроде никаких нет. Как я понял, параметры передаются в регистрах $a0..$a3.

IDA PRO - netctrl

Открываем /lib/libcommonprod.so, а в нем — искомую функцию. Она тоже начинает работу с зачистки буферов, потом считывает параметры из конфига и… О, БОЖЕ берет пароль от wifi, кодирует его в base64 и меняет на это пароль рута.

вот где собака порылась

А-а-лилуйя!

Вообщем, при каждой загрузке пароль рута устанавливается в base64(пароль от wifi). После сброса настроек — это пароль со стикера на самом роутере.

Normal startupGive root password for system maintenance (or type Control-D for normal startup): System Maintenance Mode ~ # ~ # uname -a Linux NOVA-xxxxxxxxxxxx 3.10.90 #4 Mon Jul 2 10:57:35 CST 2018 mips GNU/Linux

Мы внутри

Вообщем, сильно много интересного внутри нет. Всё разделы r/o, по-этому все в RootFS и текстовых конфигах на отдельном разделе.

~ # cat /proc/cpuinfo

system type             : RTL8197F machine                 : Unknown processor               : 0 cpu model               : MIPS 24Kc V8.5 BogoMIPS                : 666.41 wait instruction        : yes microsecond timers      : yes tlb_entries             : 64 extra interrupt vector  : yes hardware watchpoint     : yes, count: 4, address/irw mask: [0x0ffc, 0x0ffc, 0x0ffb, 0x0ffb] isa                     : mips1 mips2 mips32r2 ASEs implemented        : mips16 shadow register sets    : 4 kscratch registers      : 0 core                    : 1 VCED exceptions         : not available VCEI exceptions         : not available

~ # ls -l /sys/class/gpio/

total 0 --w-------    1 root     root         16384 Jan  1  1970 export lrwxrwxrwx    1 root     root             0 Jan  1  1970 gpio18 -> ../../devices/virtual/gpio/gpio18 lrwxrwxrwx    1 root     root             0 Jan  1  1970 gpio19 -> ../../devices/virtual/gpio/gpio19 lrwxrwxrwx    1 root     root             0 Jan  1  1970 gpio58 -> ../../devices/virtual/gpio/gpio58 lrwxrwxrwx    1 root     root             0 Jan  1  1970 gpiochip0 -> ../../devices/virtual/gpio/gpiochip0 --w-------    1 root     root         16384 Jan  1  1970 unexport

~ # ls -l /sys/devices/platform/

total 0 drwxr-xr-x    2 root     root             0 Jul 18 21:12 alarmtimer drwxr-xr-x    2 root     root             0 Jul 18 21:12 rtl819x_8367r_i2c_pin.1 drwxr-xr-x    2 root     root             0 Jul 18 21:12 rtl819x_8367r_i2c_pin.2 drwxr-xr-x    2 root     root             0 Jul 18 21:12 rtl819x_8367r_reset_pin.0 drwxr-xr-x    2 root     root             0 Jul 18 21:12 rtl819x_btn.0 drwxr-xr-x    2 root     root             0 Jul 18 21:12 rtl819x_led.0 drwxr-xr-x    2 root     root             0 Jul 18 21:12 rtl819x_led.1 drwxr-xr-x    2 root     root             0 Jul 18 21:12 rtl819x_led.2 drwxr-xr-x    3 root     root             0 Jan  1  1970 serial8250 drwxr-xr-x    3 root     root             0 Jan  1  1970 spi-sheipa.0 -rw-r--r--    1 root     root         16384 Jul 18 21:12 uevent

~ # ps

PID   USER     TIME   COMMAND     1 root       0:01 init     2 root       0:00 [kthreadd]     3 root       0:40 [ksoftirqd/0]     4 root       0:00 [kworker/0:0]     5 root       0:00 [kworker/0:0H]     6 root       0:01 [kworker/u2:0]     7 root       0:00 [khelper]     8 root       0:00 [kworker/u2:1]    75 root       0:00 [writeback]    78 root       0:00 [bioset]    79 root       0:00 [crypto]    81 root       0:00 [kblockd]    84 root       0:01 [spi0]   102 root       0:00 [kworker/0:1]   106 root       0:00 [kswapd0]   154 root       0:00 [fsnotify_mark]   708 root       0:00 [mtdblock0]   713 root       0:00 [mtdblock1]   718 root       0:00 [mtdblock2]   723 root       0:00 [mtdblock3]   728 root       0:00 [mtdblock4]   733 root       0:00 [mtdblock5]   738 root       0:00 [mtdblock6]   743 root       0:00 [mtdblock7]   748 root       0:00 [mtdblock8]   802 root       0:00 [deferwq]   860 root       0:03 klogd -n   862 root       0:00 monitor   863 root       1:55 sh /usr/bin/ugw_watchdog.sh   869 root       0:00 syslogd -f /var/etc/syslog.conf -s 50   914 root       0:15 cfmd  1030 root       0:00 [jffs2_gcd_mtd7]  1032 root       0:11 timer  1033 root       0:00 logserver  1034 root       0:14 netctrl  1069 root       0:01 device_list  1071 root       3:20 sh /usr/bin/mesh_op.sh  1530 root       0:10 pann  1531 root       0:00 gpio_ctrl  1532 root       0:00 mesh_status_check  1534 root       0:19 network_check  1570 root       0:00 redis-server /etc_ro/redis.conf  1571 root       0:01 cmdsrv -l tcp://0.0.0.0:12598 -R tcp://127.0.0.1:6379  1572 root       0:00 [kworker/0:1H]  1573 root       0:05 confsrv  1599 root       0:01 dhcps -C /etc/dhcps.conf -l /etc/dhcps.leases -x /etc/dhc  1931 root       0:00 ucloud -l 4  1962 root       0:00 sntp 1 28800 43200  2370 root       0:00 ftd -br br0 -w wlan0 wlan1 -pid /var/run/ft.pid -c /tmp/f  2375 root       0:00 pathsel -i wlan-msh -P -t 9  2387 root       0:00 multiWAN  2488 root       0:00 dhcpcd_wan1 -c /etc/wan1.ini -m 1 eth1 -h NOVA-0495e61a96  2567 root       0:00 dnrd -t 3 -M 600 --cache=off -b -R /etc/dnrd -r 3 -s 192.  2955 root       0:00 miniupnpd -f /etc/miniupnpd.config -w  2991 root       0:00 igmpproxy 10388 root       0:00 -sh 12125 root       0:00 sleep 5 12155 root       0:00 sleep 1 12156 root       0:00 ps

Access granted, root

Собственно, рутовый доступ получен. Позитивные эмоции получены. Приятно же иметь доступ ко всему, чем владеешь. А то эта эпоха всё позакрывать и выдавать черные ящики с сюрпризами мне очень не нравится.

А что дальше?

А дальше хочется вернуться к изначальной проблеме — прибить DHCP сервер. Это для начала.
Для этого надо будет изучить процессы загрузки, скрипты. Всё это осложняется пока что отсутствием возможности перепаковать образ прошивки — надо копать RSDK.

Кроме того, достаточно интересно пощупать на наличие китайских бэкдоров. Ну и, если прошивку не удасться перепаковать, поковырять cloud протокол, чтобы таки получить доступ снаружи.

Но, в любом случае, я получил массу удовольствия в процессе раскопок.

Ссылки

  1. Все файлы, логи и пр. доступны у меня в репозитории на https://github.com/latonita/tenda-reverse
  2. Tenda Mesh3-18 (Nova MW6 2018) on wikidevi.com
  3. SPI Flash programmer by SKProj на сайте Технохрень
  4. flashrom homepage
  5. firmware-mod-kit (давно заброшен)
  6. Достаточно интересный проект по эмуляции и анализу linux-based firmware — firmadyne
  7. Кладезь для анализа и автоматической перепаковки — Firmware Analysis Toolkit


ссылка на оригинал статьи https://habr.com/ru/post/460591/

Автоматическая фотостудия, часть 1

Полтора года назад я просматривал блог одного из успешных российских фотографов-портретистов с узнаваемым стилем и в голову закралась мысль, а почему бы просто не поставить камеру на штатив, один раз поставить в студии свет, выставить все настройки камеры и сделать автоматическую обработку фотографий с заданным профилем? Фотографии в блоге были великолепные, но очень похожи друг на друга.

Так как я отношусь к людям, которые не умеют фотографировать на телефон и любят фотоаппараты, то идея мне очень понравилась. Да, я видел всякие фотобудки и фотостойки, но разработчики этих устройств даже не осилили сделать нормальные цвета. Я решил, что это из-за того что разработчики не разбирались в фотографии.

Чтобы с этой идеей не произошло того же, что и с остальными (которые не сдвинулись с места или заглохли на начальном этапе). Я решил, что самое главное — сделать чтобы все работало целиком, а не полировать до блеска какой-то отдельный компонент. А так как времени на разработку у меня очень мало, после основной full-time работы остаются силы на 1-2 часа максимум, и немного больше в выходные, то нужно стараться не изучать ничего нового, по-максимуму пользоваться имеющимися знаниями.

Хочу в этой статье рассказать, какие проблемы у меня возникали на пути и как я их решал.

Небольшое объяснение по условиям съемки и оборудованию: рассматривал только фотоаппараты с матрицей APS-C минимум и профессиональные студийные вспышки, только так можно гарантированно обеспечить высокое качество снимков в любое время дня и ночи.

Все люди разного роста.

Первое, что я с удивлением обнаружил, когда поставил камеру на штатив — что не так то просто влезть в кадр да еще и так, чтобы была хорошая композиция. Когда перемещаешься от камеры и к ней, то тоже вся композиция портится, если правильно ее поставить для конкретного человека стоящего в определенной точке. Да, можно поставить стул и сказать, что надо сидеть на стуле, но это будет не очень интересно. Еще можно обрезать фотографии, но тогда будет сильно ухудшаться качество. Ну и последний путь, который я выбрал — сделать чтобы камера наводилась автоматически.

Здесь есть тоже 2 варианта. Правильный — оптическая ось всегда горизонтальна, камера смещается вверх и вниз и более простой в реализации — подстраивать положение камеры наклонами. В этом случае будут перспективные искажения, но они довольно неплохо исправляются при обработке если запоминать угол наклона камеры.

Так как опыта изготовления всяких железных устройств я практически не имел, то попытался найти что-то максимально готовое к использованию. Нашел несколько устройств для панорамной съемки в пределах 1000$, все позволяли вручную управлять наклонами и поворотами, а также автоматически снимать панорамы. Но управлять с компьютера ими было нельзя. Также есть довольно много устройств для управления видеокамерами, для съемки с операторских кранов, например. Хорошие устройства, которые имеют намеки на цифровое управление стоят очень дорого, при этом совершенно непонятно, есть ли там какое-то доступное API. В итоге нашел вот такой девайс на популярном сайте:

Из электроники нет ничего. Год назад была доступна только версия с коллекторными двигателями (со встроенными редукторами), её я и купил. Надо было как-то этой штукой управлять с компьютера. На форуме нашего института подсказали, что самый доступный способ — это воспользоваться Arduino. Так я и сделал. Купил еще motor shield, так как двигатели там питаются от 12 вольт. После того, как я попытался это включить я ощутил всю боль которую могут причинить коллекторные двигатели человеку — их не только невозможно повернуть на заданный угол, просто «немного повернуть» тоже непросто. Первая мысль была — поставить туда шаговый двигатель. Я очень долго искал шаговый двигатель, который влезет в эту платформу вместо того, который там стоял, но так и не нашел. Потом стал продумывать, как туда можно прикрутить сервопривод, даже его купил но тоже ничего надежного придумать не смог. Следующая мысль была — прикрутить к платформе акселерометр и понемногу поворачивать платформу до заданного угла. Прикрутил акселерометр с гироскопом и компасом, но он уж очень сильно глючил и от этой идеи я тоже отказался (через месяц я понял, что в глюках акселерометра был виноват китайский блок питания для фотоаппарата, от которого шли неслабые наводки). И тут я случайно прочитал, как устроен сервопривод. Идея прикрутить резистор для измерения угла мне понравилась, но надо было как-то соединить его со шкивом. Пришлось освоить FreeCAD и впервые в жизни воспользоваться услугой 3D печати. Короче после обработки напильником все удалось собрать.

С программой для ардуино для установки заданного угла пришлось помучаться, так как у камеры на платформе большой момент инерции и останавливается она не сразу. Но в итоге получилось устанавливать угол с точностью около 1 градуса.

Теперь про автоматическое наведение — идея простая сделать чтобы лицо было в верхней части кадра. Так что надо просто на каждой картинке из liveview находить лицо и подстраивать платформу. Про определение лиц я тогда ничего не знал, так что по тьюториалу воспользовался методом с использованием признаков Хаара (haar cascades). Выяснил, что для лиц этот метод не работает. Находит на каждом кадре еще кучу мусора кроме того что нужно и потребляет очень много процессорного времени. Потом нашел еще один пример, как использовать нейросети через OpenCV. Нейросети работают просто отлично! Но радовался я до того момента как запустил параллельно обработку фотографий. И линукс как-то плохо стал между тредом управления платформой и процессами обработки фото распределять процессорное время. Пошел по пути наименьшего сопротивления — стал делать определение лиц на видеокарте. Все стало работать отлично.

Несмотря на то, что я не хотел углубляться в детали, все-таки провел небольшой тест. И еще купил Intel Neural Compute Stick 2 — попробовал на нем считать вместо видеокарты. Результаты у меня примерно такие (цифры — время обработки одного изображения размером 800×533) —

  • Core i5 9400F — 59
  • Core i7 7500U — 108
  • Core i7 3770 — 110
  • GeForce GTX 1060 6Gb — 154
  • GeForce GTX 1050 2Gb — 199
  • Core i7 3770, ubuntu 18.04 with opencv from OpenVINO — 67
  • Intel Neural Compute Stick 2, ubuntu 18.04 with opencv from OpenVINO — 349

Оказалось, что достаточно обрабатывать изображения размером 300 по меньшей стороне, чтобы надежно находилось лицо человека, стоящего в полный рост в кадре. На таких изображениях работает быстрее. Сейчас у меня используется GeForce GTX 1050. Уверен, можно сильно улучшить, но сейчас есть гораздо более серьезная проблема.

Экспозиция

Не секрет, что фотография должна быть правильно экспонирована. В моем случае это еще более важно, так как нет ретуши. Чтобы дефекты кожи были менее заметны, фото должно быть максимально светлое, на грани пересвета, но без пересветов.

Яркость итоговой картинки при съемке со вспышкой зависит от следующих параметров:

  • Мощность вспышки
  • Расстояние от вспышки до объекта съемки
  • Диафрагма
  • Значение ISO
  • Параметры при конвертации из RAW

После того, как сделан кадр мы можем менять только последний параметр. Но менять его в широких пределах не очень хорошо, так как при большой положительной коррекции экспозиции темного кадра будут шумы, а в обратном случае может быть клиппинг в светлых участках.

Для автоматического определения экспозиции во время съемки со вспышкой используется система TTL (Through The Lens). Работает следующим образом:

  1. Вспышка делает серию мелких вспышек.
  2. В это время камера делает замер экспозиции, фокусируется и замеряет расстояние до объекта фокусировки.
  3. На основе этих данных рассчитывает требуемую мощность вспышки.
  4. Вспышка срабатывает еще раз, и в этом время открывается затвор, делается снимок.

Эта система отлично работает, когда есть возможность вручную подкорректировать снимки после съемки. Но для получения готового результата она работает неудовлетворительно. Если что — пробовал вспышки Profoto за >100т.р.

У меня условия известные, вспышки должны стоять все время на одном месте. Так что можно просто рассчитать экспозицию по положению человека в пространстве. Возникает задача — как определить положение человека?

Первая идея была просто брать расстояние до объекта фокусировки из EXIF и для первого кадра делать большую экспокоррекцию в рав-конвертере а для следующего подстраивать мощность вспышки или диафрагму. Очень большая вероятность, что человек будет делать много кадров, стоя на одном месте. Но оказалось, что расстояние в EXIF пишется сильно дискретное, чем дальше объект — тем больше шаг. Причем для разных объективов расстояние до объекта принимает разные наборы значений, а некоторые вообще его не измеряют.

Следующая идея — использовать ультразвуковой дальномер. Этот прибор измеряет расстояние довольно точно, но только до метра и только если человек не одет во что-то, что поглощает звуковые волны. Если поставить дальномер на сервопривод и крутить его как радар, то становится чуть лучше — измеряет уже до 1.5 метров, что тоже очень мало (лучше всего люди получаются, если снимать их с расстояния 2 метра).

Конечно я знал, что уже даже недорогие телефоны стоят карты глубин и размывают фон выборочно. Но так не хотелось в это ввязываться. К сожалению, выбора не осталось. Сначала хотел купить 2 вебкамеры, объединить их и считать карту смещений с помощью OpenCV. Но, к счастью, нашел много камер глубины которые уже внутри себя это делают. Остановил выбор на Intel D435 (если кто-то захочет такую купить — она в линуксе в основной ветке ядра не поддерживается. В репозитории librealsense есть патчи для debian и ubuntu вроде. Для fedora пришлось их править).

Как только все подключил, написал тестовую программу, которая измеряет расстояние до небольшого квадрата в центре. Так до сих пор этот код и работает. И работает довольно неплохо. Конечно надо на картинке с RGB камеры искать лицо и вычислять расстояние от вспышки до этого лица. Но это планы на будущее.

По положению человека в пространстве надо вычислить поправку к экспозиции. Сначала я придумал какую-то формулу, которая работала только для точечного источника света в вакууме (на самом деле имело значение отсутствие отражающих стен и потолка). Но потом просто сделал серию кадров с постоянной мощностью вспышки и в рав-конвертере на глаз откорректировал экспозицию, оказалось, что поправка практически линейно зависит от расстояния. У меня используется схема освещения Рембрандта, вспышка с софтбоксом стоит в плоскости камеры.

Но с поправкой экспозиции тоже что-то надо делать. В идеале надо менять мощность вспышки, но пока у меня меняется диафрагма и добавок <1/6Ev — в рав-конвертере. Синхронизатор моих вспышек может управляться по bluetooth с помощью приложения для телефона. Так что в будущем планирую разобраться, как там протокол устроен и менять мощность вспышек.

Вот сравнение постоянной мощности вспышки с TTL и моим методом. Работает гораздо стабильнее и точнее TTL:

Разнообразие

Когда девушка (или даже парень) приходит на фотосессию к фотографу она (или он) обычно хочет фото разного плана, более крупного, где только лицо и более общего — в полный рост или по пояс. Не все знают, но лучше всего план меняется сменой фокусного расстояния объектива. То есть человек всегда стоит на расстоянии скажем 2 метра, если нам надо снять в полный рост — накручиваем объектив 35мм, если только лицо — 135мм, а если по пояс — то 50мм или 85мм. Ну или не меняем объективы а ставим объектив с зумом. Предлагать пользователю руками крутить зум на камере, которая стоит на подвижной платформе, прорываясь через пучок проводов — звучит как-то не очень. Так что купил пачку запчастей на алиэкспрессе, взял сервопривод который мне не пригодился для управления платформой и сделал вот это:

А вот так оно работает:

Результаты первого теста в фотостудии, прежде всего хотелось посмотреть, насколько разнообразные получится делать снимки, ничего не двигали и не перенастраивали во время съемки:

Видео процесса:

Результат

Вот это одни из лучших кадров, которые получилось сделать:

вроде у всех разрешение на публикацию спрашивали, если вы себя узнали и хотите убрать фото — напишите мне

Для чего я это делал? Это штука которой еще не было, по-крайней мере я не нашел ничего похожего. Потенциально полезная — сейчас много специалистов, таких как психологи, бизнес-тренеры, спортивные тренеры, парикмахеры продают свои услуги через блоги, им нужно много фотографий, причем именно в таком виде, в каком им хочется, а не фотографу. Некоторые люди просто не любят, когда на них при съемке смотрит незнакомый человек (фотограф). Ну и самое простое — это отличное развлечение для корпоративов, выставок и других мероприятий.

Сейчас аппарат стоит в студии Citrusfoto, очень благодарен, что согласились его там временно разместить! Записывайтесь на съёмку вот здесь — https://ugoloc.ru/studios/booking/1207! Большое спасибо парням из сервиса бронирования фотостудий ugoloc.ru!

Не описал программную часть, как обрабатываются фотографии и про взаимодействие с пользователем, так как уже и так много текста, напишу позже вторую часть. Эти моменты уже довольно неплохо проработаны так, что системой могут пользоваться люди не знакомые с программированием.

Сайт проекта — http://ixshot.com.


ссылка на оригинал статьи https://habr.com/ru/post/460605/