mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-10-29 09:32:34 +00:00
Compare commits
203 Commits
v2.5.0-rc1
...
v2.6.0-rc5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4c21f5c4b6 | ||
|
|
cf657dbd94 | ||
|
|
33c9876760 | ||
|
|
4d6d7405d6 | ||
|
|
e249701c34 | ||
|
|
0d50975152 | ||
|
|
6d87847d15 | ||
|
|
eebe021780 | ||
|
|
c6e0384f21 | ||
|
|
23ae850f72 | ||
|
|
708cf2dec6 | ||
|
|
a95745d95b | ||
|
|
83ccea0abf | ||
|
|
bfeaf89238 | ||
|
|
7439217b3c | ||
|
|
ae2377f4d2 | ||
|
|
b81d0aaf0e | ||
|
|
1546bef93f | ||
|
|
32b1aade42 | ||
|
|
2a92b75fe1 | ||
|
|
cb30d9e20a | ||
|
|
588206b93b | ||
|
|
6399649038 | ||
|
|
aa3cb95233 | ||
|
|
3ea06dac40 | ||
|
|
a70dda4a8e | ||
|
|
a01f1add81 | ||
|
|
57849591d7 | ||
|
|
b4a09e7167 | ||
|
|
96bb8b1372 | ||
|
|
99ea9da785 | ||
|
|
bfe7fadfc5 | ||
|
|
ad1dcc4f45 | ||
|
|
f371c789d0 | ||
|
|
386eca1f65 | ||
|
|
8b9047952d | ||
|
|
5a105ef06e | ||
|
|
c60dc1e045 | ||
|
|
1e1bd19429 | ||
|
|
cfe07f6e15 | ||
|
|
a64039db20 | ||
|
|
7f81ddb8cc | ||
|
|
3c0d495334 | ||
|
|
38a7c54cce | ||
|
|
1aead07444 | ||
|
|
d2f44cbb12 | ||
|
|
43d7ca31d6 | ||
|
|
0985c573b0 | ||
|
|
d9ed861c1d | ||
|
|
8ef9989147 | ||
|
|
7d5eab4bf3 | ||
|
|
5e03e04bbd | ||
|
|
6fabaeca53 | ||
|
|
be4ca445f5 | ||
|
|
e99c8b27e1 | ||
|
|
e9055b4f08 | ||
|
|
cfcafb676b | ||
|
|
899b4d6bfd | ||
|
|
2003632ddb | ||
|
|
d4a14106b7 | ||
|
|
85af9d7e0b | ||
|
|
d4442efbfe | ||
|
|
3a26ae2695 | ||
|
|
09af596e85 | ||
|
|
5985187316 | ||
|
|
33ac83a309 | ||
|
|
921c1b553d | ||
|
|
d160507230 | ||
|
|
7368620fd2 | ||
|
|
a910e297a3 | ||
|
|
f819bb8753 | ||
|
|
cc0d4bded2 | ||
|
|
e3b2b7f232 | ||
|
|
c8dde50eba | ||
|
|
3c355f96eb | ||
|
|
93dd24ef6e | ||
|
|
107bc8ef65 | ||
|
|
9a8278afcc | ||
|
|
1c48765913 | ||
|
|
c6a45184fd | ||
|
|
18d5b8cba7 | ||
|
|
65c08ade18 | ||
|
|
3f6fee91e9 | ||
|
|
d29c4e49b3 | ||
|
|
f162000749 | ||
|
|
c804333bc0 | ||
|
|
449795db97 | ||
|
|
af92a2c7aa | ||
|
|
b68affdf6a | ||
|
|
7a95f9ac2d | ||
|
|
8b5d9d84de | ||
|
|
93d93c7708 | ||
|
|
b35232ab4a | ||
|
|
770a2bdd36 | ||
|
|
9650f8eaa8 | ||
|
|
63ab76bb30 | ||
|
|
fcb21ca0b6 | ||
|
|
d6d5422152 | ||
|
|
5b970a3f12 | ||
|
|
a4a7c1f9f3 | ||
|
|
5cbac23e3f | ||
|
|
172c0d3690 | ||
|
|
535f41d58b | ||
|
|
2be18091a4 | ||
|
|
73f42e3c6f | ||
|
|
cff778d8ca | ||
|
|
94d4498a2d | ||
|
|
eb0ab17f58 | ||
|
|
1ab99d50b2 | ||
|
|
dfeddc0d89 | ||
|
|
efde86be9d | ||
|
|
739e8c12fb | ||
|
|
3fdbbff9f7 | ||
|
|
0a56755bef | ||
|
|
c35290772d | ||
|
|
cedcbcbc2b | ||
|
|
9de96deca8 | ||
|
|
19dbb1d5e3 | ||
|
|
83b6ccf562 | ||
|
|
ea86593835 | ||
|
|
36b5478005 | ||
|
|
1ad19297c1 | ||
|
|
f5357f7854 | ||
|
|
8a3140b89b | ||
|
|
16e0724ace | ||
|
|
17ff9eecf5 | ||
|
|
4b870f978c | ||
|
|
8b83365961 | ||
|
|
c6ebb5537a | ||
|
|
6ebe189d71 | ||
|
|
98b56551d5 | ||
|
|
606e27e256 | ||
|
|
94fe14b9f9 | ||
|
|
58388f84b6 | ||
|
|
79ea04af49 | ||
|
|
396e2bd06c | ||
|
|
1a484c7f39 | ||
|
|
e6b1030991 | ||
|
|
6e32e68302 | ||
|
|
0f13f7f5cd | ||
|
|
2ac4f9ef1d | ||
|
|
f1a75c25f9 | ||
|
|
ff8d70753d | ||
|
|
caea6baecd | ||
|
|
2e914c9b35 | ||
|
|
da65d7e06f | ||
|
|
d18eef480c | ||
|
|
f3532c66e5 | ||
|
|
9678b1d6a5 | ||
|
|
379a4e2382 | ||
|
|
edb33cd560 | ||
|
|
2ff425ddeb | ||
|
|
7d016ac27f | ||
|
|
9790377dec | ||
|
|
597c547101 | ||
|
|
73b2645027 | ||
|
|
8d58387d15 | ||
|
|
54dac4d348 | ||
|
|
a0880ed0f1 | ||
|
|
ed6d683980 | ||
|
|
4c72c6a35a | ||
|
|
125d56866e | ||
|
|
a70a767ec0 | ||
|
|
b8a6764207 | ||
|
|
98c9fcfd5d | ||
|
|
eac5504fec | ||
|
|
c2c75b67eb | ||
|
|
ef3eacefa7 | ||
|
|
ef7481596a | ||
|
|
6f4e00aa46 | ||
|
|
be65578a7f | ||
|
|
20d4bd0c7d | ||
|
|
531f4eb811 | ||
|
|
3b0dae7189 | ||
|
|
79395593ba | ||
|
|
61248b98e0 | ||
|
|
72b5abb72a | ||
|
|
673a029a02 | ||
|
|
7efb85180f | ||
|
|
f95eadaa8f | ||
|
|
6f6b40a94f | ||
|
|
d84982f161 | ||
|
|
4b07afe59f | ||
|
|
5d53d138b0 | ||
|
|
e40631b8cd | ||
|
|
22135129bd | ||
|
|
de4b3c4edc | ||
|
|
e3b1fe36e5 | ||
|
|
5af7e1e7d8 | ||
|
|
057ebb8660 | ||
|
|
17fe72c6e9 | ||
|
|
834ff2fe4f | ||
|
|
ce3849e131 | ||
|
|
66640cdd1a | ||
|
|
300924a4be | ||
|
|
8fb088bcc8 | ||
|
|
b08455228f | ||
|
|
09563eadaf | ||
|
|
2df46a2c77 | ||
|
|
e4fa57b4d0 | ||
|
|
48677a6943 | ||
|
|
e79970ce04 | ||
|
|
b4d1d58fc9 |
39
.github/actions/create-ami-from-image/action.yml
vendored
Normal file
39
.github/actions/create-ami-from-image/action.yml
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
name: Create AMI from firmware image in S3 bucket
|
||||
|
||||
inputs:
|
||||
firmware_image_name:
|
||||
description: Name of the firmware image
|
||||
required: true
|
||||
firmware_image_s3_bucket:
|
||||
description: Name of the S3 bucket where the image resides
|
||||
required: true
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Import snapshot based on firmware image
|
||||
id: import_snapshot
|
||||
shell: bash
|
||||
run: |
|
||||
echo ::set-output name=import_task_id::$(aws ec2 import-snapshot --description '${{ inputs.firmware_image_name }}' --disk-container 'Format=raw,UserBucket={S3Bucket=${{ inputs.firmware_image_s3_bucket }},S3Key=${{ inputs.firmware_image_name }}}' | jq -r '.ImportTaskId')
|
||||
|
||||
- name: Wait for import task to complete and get snapshot ID
|
||||
id: get_snapshot_id
|
||||
shell: bash
|
||||
run: |
|
||||
IMPORT_TASK_STATUS=""
|
||||
while [[ $IMPORT_TASK_STATUS != 'completed' ]]; do
|
||||
IMPORT_TASK_STATUS=$(aws ec2 describe-import-snapshot-tasks --import-task-ids ${{ steps.import_snapshot.outputs.import_task_id }} | jq -r '.ImportSnapshotTasks[].SnapshotTaskDetail.Status')
|
||||
echo "Import task status is $IMPORT_TASK_STATUS, waiting for completion."
|
||||
done
|
||||
echo ::set-output name=id::$(aws ec2 describe-import-snapshot-tasks --import-task-ids ${{ steps.import_snapshot.outputs.import_task_id }} | jq -r '.ImportSnapshotTasks[].SnapshotTaskDetail.SnapshotId')
|
||||
|
||||
- name: Tag snapshot with image name
|
||||
shell: bash
|
||||
run: |
|
||||
aws ec2 create-tags --resources ${{ steps.get_snapshot_id.outputs.id }} --tags 'Key=Name,Value=${{ inputs.firmware_image_name }}'
|
||||
|
||||
- name: Register AMI based on snapshot
|
||||
shell: bash
|
||||
run: |
|
||||
aws ec2 register-image --name '${{ inputs.firmware_image_name }}' --root-device-name /dev/xvda --block-device-mappings 'DeviceName=/dev/xvda,Ebs={SnapshotId=${{ steps.get_snapshot_id.outputs.id }}}'
|
||||
36
.github/workflows/build-dev.yml
vendored
36
.github/workflows/build-dev.yml
vendored
@@ -1,5 +1,13 @@
|
||||
name: Build OpenWrt/uCentral images
|
||||
|
||||
env:
|
||||
AWS_DEFAULT_OUTPUT: json
|
||||
AWS_DEFAULT_REGION: us-east-1
|
||||
AWS_S3_BUCKET_NAME: ucentral-ap-firmware
|
||||
AWS_ACCOUNT_ID: ${{ secrets.UCENTRAL_S3_ACCOUNT_ID }}
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.UCENTRAL_S3_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.UCENTRAL_S3_ACCESS_KEY_SECRET }}
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main, next, staging-* ]
|
||||
@@ -8,10 +16,12 @@ on:
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
x64_vm_image_name: ${{ steps.package_and_upload_image.outputs.x64_vm_image_name }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
target: ['actiontec_web7200', 'cig_wf188n', 'cig_wf194c', 'cig_wf194c4', 'cig_wf160d', 'cig_wf808', 'cybertan_eww622-a1', 'edgecore_eap101', 'edgecore_eap102', 'edgecore_ecs4100-12ph', 'edgecore_ecw5211', 'edgecore_ecw5410', 'edgecore_oap100', 'edgecore_ssw2ac2600', 'edgecore_spw2ac1200', 'edgecore_spw2ac1200-lan-poe', 'hfcl_ion4', 'hfcl_ion4xe', 'hfcl_ion4xi', 'indio_um-305ac', 'linksys_ea6350-v4', 'linksys_e8450-ubi', 'linksys_ea8300', 'tp-link_ec420-g1', 'tplink_ex227', 'tplink_ex228', 'tplink_ex447', 'wallys_dr40x9', 'wallys_dr6018', 'wallys_dr6018_v4' ]
|
||||
target: ['actiontec_web7200', 'cig_wf188n', 'cig_wf194c', 'cig_wf194c4', 'cig_wf196', 'cig_wf610d', 'cig_wf808', 'cybertan_eww622-a1', 'edgecore_eap101', 'edgecore_eap102', 'edgecore_eap104', 'edgecore_ecs4100-12ph', 'edgecore_ecw5211', 'edgecore_ecw5410', 'edgecore_oap100', 'edgecore_ssw2ac2600', 'edgecore_spw2ac1200', 'edgecore_spw2ac1200-lan-poe', 'hfcl_ion4', 'hfcl_ion4xe', 'hfcl_ion4xi', 'indio_um-305ac', 'indio_um-305ax', 'indio_um-325ac', 'indio_um-510ac-v3', 'indio_um-550ac', 'linksys_ea6350-v4', 'linksys_e8450-ubi', 'linksys_ea8300', 'tp-link_ec420-g1', 'tplink_ex227', 'tplink_ex228', 'tplink_ex447', 'udaya_a5-id2', 'wallys_dr40x9', 'x64_vm' ]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
@@ -24,17 +34,12 @@ jobs:
|
||||
make -j TARGET=${{ matrix.target }}
|
||||
|
||||
- name: Package and upload image for ${{ matrix.target }}
|
||||
id: package_and_upload_image
|
||||
env:
|
||||
GH_BUILD_USERNAME: ${{ secrets.GH_BUILD_USERNAME }}
|
||||
GH_BUILD_PASSWORD: ${{ secrets.GH_BUILD_PASSWORD }}
|
||||
ARTIFACTORY_USERNAME: cicd-indoor-main
|
||||
ARTIFACTORY_PASSWORD: ${{ secrets.ARTIFACTORY_PASSWORD }}
|
||||
AWS_S3_BUCKET_NAME: ucentral-ap-firmware
|
||||
AWS_DEFAULT_OUTPUT: json
|
||||
AWS_DEFAULT_REGION: us-east-1
|
||||
AWS_ACCOUNT_ID: ${{ secrets.UCENTRAL_S3_ACCOUNT_ID }}
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.UCENTRAL_S3_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.UCENTRAL_S3_ACCESS_KEY_SECRET }}
|
||||
run: |
|
||||
LOWERCASE_TARGET=`echo ${{ matrix.target }} | tr '[:upper:]' '[:lower:]'`
|
||||
HASH=$(git rev-parse --short HEAD)
|
||||
@@ -66,6 +71,10 @@ jobs:
|
||||
[ -f openwrt/tmp/image-file ] && aws s3 cp --acl public-read --content-type "application/json" "latest-upgrade.json" "s3://$AWS_S3_BUCKET_NAME/$JSON_NAME"
|
||||
[ -f openwrt/tmp/image-file ] && aws s3api put-object-tagging --bucket "$AWS_S3_BUCKET_NAME" --key "$JSON_NAME" --tagging "{\"TagSet\":[{\"Key\":\"release\",\"Value\":\"$IS_RELEASE\"}]}"
|
||||
|
||||
if [ ${{ matrix.target }} == 'x64_vm' ]; then
|
||||
echo ::set-output name=x64_vm_image_name::"$(echo $IMG_NAME)"
|
||||
fi
|
||||
|
||||
trigger-testing:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
@@ -78,3 +87,16 @@ jobs:
|
||||
repository: Telecominfraproject/wlan-testing
|
||||
event-type: new-ap-release
|
||||
client-payload: '{"ref": "${GITHUB_REF#refs/tags/}", "sha": "${{ github.sha }}"}'
|
||||
|
||||
create-x64_vm-ami:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Use create-ami-from-image composite action
|
||||
uses: ./.github/actions/create-ami-from-image
|
||||
with:
|
||||
firmware_image_name: ${{ needs.build.outputs.x64_vm_image_name }}
|
||||
firmware_image_s3_bucket: ${{ env.AWS_S3_BUCKET_NAME }}
|
||||
|
||||
88
.github/workflows/x64_vm-build-test.yml
vendored
Normal file
88
.github/workflows/x64_vm-build-test.yml
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
name: Test x64_vm build and AMI creation
|
||||
|
||||
env:
|
||||
AWS_DEFAULT_OUTPUT: json
|
||||
AWS_DEFAULT_REGION: us-east-1
|
||||
AWS_S3_BUCKET_NAME: ucentral-ap-firmware
|
||||
AWS_ACCOUNT_ID: ${{ secrets.UCENTRAL_S3_ACCOUNT_ID }}
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.UCENTRAL_S3_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.UCENTRAL_S3_ACCESS_KEY_SECRET }}
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
x64_vm_image_name: ${{ steps.package_and_upload_image.outputs.x64_vm_image_name }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
target: ['x64_vm']
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Build image for ${{ matrix.target }}
|
||||
id: build
|
||||
run: |
|
||||
git config --global user.email "you@example.com"
|
||||
git config --global user.name "Your Name"
|
||||
make -j TARGET=${{ matrix.target }}
|
||||
|
||||
- name: Package and upload image for ${{ matrix.target }}
|
||||
id: package_and_upload_image
|
||||
env:
|
||||
GH_BUILD_USERNAME: ${{ secrets.GH_BUILD_USERNAME }}
|
||||
GH_BUILD_PASSWORD: ${{ secrets.GH_BUILD_PASSWORD }}
|
||||
ARTIFACTORY_USERNAME: cicd-indoor-main
|
||||
ARTIFACTORY_PASSWORD: ${{ secrets.ARTIFACTORY_PASSWORD }}
|
||||
run: |
|
||||
LOWERCASE_TARGET=`echo ${{ matrix.target }} | tr '[:upper:]' '[:lower:]'`
|
||||
HASH=$(git rev-parse --short HEAD)
|
||||
|
||||
if [[ ${GITHUB_REF} == "refs/heads/"* ]]
|
||||
then
|
||||
REF=$(echo ${GITHUB_REF#refs/heads/} | tr '/' '-')
|
||||
IS_RELEASE="false"
|
||||
else
|
||||
REF=$(echo ${GITHUB_REF#refs/tags/} | tr '/' '-')
|
||||
IS_RELEASE="true"
|
||||
fi
|
||||
|
||||
BASENAME="$(date +%Y%m%d)-$LOWERCASE_TARGET-$REF-$HASH"
|
||||
TAR_NAME="$BASENAME.tar.gz"
|
||||
IMG_NAME="$BASENAME-upgrade.bin";
|
||||
JSON_NAME="$BASENAME.json";
|
||||
|
||||
tar cfz "$TAR_NAME" -C openwrt/bin/targets/ .
|
||||
curl -s -u $GH_BUILD_USERNAME:$GH_BUILD_PASSWORD -T "$TAR_NAME" "https://tip.jfrog.io/artifactory/tip-wlan-ap-firmware/uCentral/$LOWERCASE_TARGET/"$TAR_NAME""
|
||||
IMG_NAME="$BASENAME-upgrade.bin";
|
||||
TIP_VERSION="$(grep DISTRIB_TIP= openwrt/tmp/openwrt_release | cut -d\' -f2)"
|
||||
echo -e "{\n\t\"image\":\""${IMG_NAME}"\",\n\t\"revision\": \""${TIP_VERSION}"\",\n\t\"timestamp\":\""$(date +%s)"\",\n\t\"compatible\": \""${LOWERCASE_TARGET}"\"\n}" > latest-upgrade.json
|
||||
[ -f openwrt/tmp/image-file ] && curl -s -u $GH_BUILD_USERNAME:$GH_BUILD_PASSWORD -T "openwrt/$(cat openwrt/tmp/image-file)" "https://tip.jfrog.io/artifactory/tip-wlan-ap-firmware/uCentral/$LOWERCASE_TARGET/"$IMG_NAME""
|
||||
[ -f openwrt/tmp/image-file ] && curl -s -u $GH_BUILD_USERNAME:$GH_BUILD_PASSWORD -T "latest-upgrade.json" "https://tip.jfrog.io/artifactory/tip-wlan-ap-firmware/uCentral/$LOWERCASE_TARGET/latest-upgrade.json"
|
||||
|
||||
[ -f openwrt/tmp/image-file ] && aws s3 cp --acl public-read --content-type "application/octet-stream" "openwrt/$(cat openwrt/tmp/image-file)" "s3://$AWS_S3_BUCKET_NAME/$IMG_NAME"
|
||||
[ -f openwrt/tmp/image-file ] && aws s3api put-object-tagging --bucket "$AWS_S3_BUCKET_NAME" --key "$IMG_NAME" --tagging "{\"TagSet\":[{\"Key\":\"release\",\"Value\":\"$IS_RELEASE\"}]}"
|
||||
[ -f openwrt/tmp/image-file ] && aws s3 cp --acl public-read --content-type "application/json" "latest-upgrade.json" "s3://$AWS_S3_BUCKET_NAME/$JSON_NAME"
|
||||
[ -f openwrt/tmp/image-file ] && aws s3api put-object-tagging --bucket "$AWS_S3_BUCKET_NAME" --key "$JSON_NAME" --tagging "{\"TagSet\":[{\"Key\":\"release\",\"Value\":\"$IS_RELEASE\"}]}"
|
||||
|
||||
if [[ ${{ matrix.target }} == 'x64_vm' ]]; then
|
||||
echo ::set-output name=x64_vm_image_name::"$(echo $IMG_NAME)"
|
||||
fi
|
||||
|
||||
create-x64_vm-ami:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
ref: WIFI-7206-add-workflow-to-build-virtual-ap-image
|
||||
|
||||
- name: Use create-ami-from-image composite action
|
||||
uses: ./.github/actions/create-ami-from-image
|
||||
with:
|
||||
firmware_image_name: ${{ needs.build.outputs.x64_vm_image_name }}
|
||||
firmware_image_s3_bucket: ${{ env.AWS_S3_BUCKET_NAME }}
|
||||
@@ -12,7 +12,7 @@ First we need to clone and setup our tree. This will result in an openwrt/.
|
||||
Next we need to select the profile and base package selection. This setup will install the feeds, packages and generate the .config file.
|
||||
```
|
||||
cd openwrt
|
||||
./scripts/gen_config.py ea8300
|
||||
./scripts/gen_config.py linksys_ea8300
|
||||
```
|
||||
Finally we can build the tree.
|
||||
```
|
||||
|
||||
@@ -37,6 +37,9 @@ define Package/cc2652/install
|
||||
|
||||
$(INSTALL_DIR) $(1)/etc/config
|
||||
$(INSTALL_BIN) ./files/tisbl.config $(1)/etc/config/tisbl
|
||||
|
||||
$(INSTALL_DIR) $(1)/etc/uci-defaults
|
||||
$(INSTALL_BIN) ./files/tisbl.defaults $(1)/etc/uci-defaults
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,cc2652))
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
config tisbl 'tisbl'
|
||||
option firmware '/etc/tifirmware/ble5_host_test_bd9.bin'
|
||||
option tty '/dev/ttyMSM1' # for EAP101 board
|
||||
# option tty '/dev/ttyACM0' # for virtualbox openwrt 19.07 with TI CC26X2R launchpad
|
||||
option tichip '2652'
|
||||
option baudrate '115200'
|
||||
option resetpin '79'
|
||||
option backdoorpin '34' #EAP101-R1
|
||||
# option backdoorpin '67' #EAP101-R0A-HW-modification
|
||||
option firmware '/etc/tifirmware/ble5_host_test_bd9.bin'
|
||||
option tty '/dev/ttyMSM1'
|
||||
option tichip '2652'
|
||||
option baudrate '115200'
|
||||
option resetpin '79'
|
||||
option backdoorpin '34'
|
||||
|
||||
13
feeds/bluetooth-cc2652/cc2652/files/tisbl.defaults
Executable file
13
feeds/bluetooth-cc2652/cc2652/files/tisbl.defaults
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
|
||||
. /lib/functions.sh
|
||||
. /lib/functions/system.sh
|
||||
|
||||
board=$(board_name)
|
||||
|
||||
case $board in
|
||||
edgecore,eap104)
|
||||
uci set tisbl.tisbl.backdoorpin=31
|
||||
uci set tisbl.tisbl.resetpin=35
|
||||
;;
|
||||
esac
|
||||
@@ -17,9 +17,6 @@ cig,wf194c4)
|
||||
ucidef_set_led_wlan "wlan5g" "WLAN5G" "green:wifi5" "phy0tpt"
|
||||
ucidef_set_led_wlan "wlan2g" "WLAN2G" "green:wifi2" "phy1tpt"
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$board" in
|
||||
edgecore,eap101)
|
||||
ucidef_set_led_wlan "wlan5g" "WLAN5G" "green:wifi5" "phy0tpt"
|
||||
ucidef_set_led_wlan "wlan2g" "WLAN2G" "green:wifi2" "phy1tpt"
|
||||
@@ -32,11 +29,20 @@ edgecore,eap102)
|
||||
ucidef_set_led_wlan "wlan5g" "WLAN5G" "green:wifi5" "phy0tpt"
|
||||
ucidef_set_led_wlan "wlan2g" "WLAN2G" "green:wifi2" "phy1tpt"
|
||||
;;
|
||||
edgecore,eap104)
|
||||
ucidef_set_led_wlan "wlan2g" "WLAN2G" "green:wifi2" "phy0tpt"
|
||||
ucidef_set_led_wlan "wlan5g" "WLAN5G" "green:wifi5" "phy1tpt"
|
||||
ucidef_set_led_netdev "wan" "wan" "yellow:uplink" "eth0"
|
||||
;;
|
||||
hfcl,ion4xi|\
|
||||
hfcl,ion4xe)
|
||||
ucidef_set_led_wlan "wlan5g" "WLAN5G" "blue:wifi5" "phy0tpt"
|
||||
ucidef_set_led_wlan "wlan2g" "WLAN2G" "blue:wifi2" "phy1tpt"
|
||||
;;
|
||||
glinet,ax1800|\
|
||||
glinet,axt1800)
|
||||
ucidef_set_led_netdev "wan" "WAN" "blue:wan" "eth0" "tx rx link"
|
||||
;;
|
||||
esac
|
||||
|
||||
board_config_flush
|
||||
|
||||
@@ -32,15 +32,19 @@ qcom_setup_interfaces()
|
||||
cig,wf194c4|\
|
||||
edgecore,eap106|\
|
||||
qcom,ipq5018-mp03.3|\
|
||||
yuncore,ax840|\
|
||||
motorola,q14|\
|
||||
sercomm,wallaby)
|
||||
ucidef_set_interface_lan "eth0"
|
||||
ucidef_set_interface_wan "eth1"
|
||||
;;
|
||||
edgecore,eap101)
|
||||
edgecore,eap101|\
|
||||
glinet,axt1800)
|
||||
ucidef_set_interface_lan "eth1 eth2"
|
||||
ucidef_set_interface_wan "eth0"
|
||||
;;
|
||||
edgecore,eap102|\
|
||||
edgecore,eap104|\
|
||||
wallys,dr6018|\
|
||||
cig,wf188n|\
|
||||
cig,wf196)
|
||||
@@ -51,7 +55,8 @@ qcom_setup_interfaces()
|
||||
ucidef_set_interface_lan "eth0 eth1 eth2 eth3"
|
||||
ucidef_set_interface_wan "eth4"
|
||||
;;
|
||||
wallys,dr6018-v4)
|
||||
wallys,dr6018-v4|\
|
||||
glinet,ax1800)
|
||||
ucidef_set_interface_lan "eth1 eth2 eth3 eth4"
|
||||
ucidef_set_interface_wan "eth0"
|
||||
;;
|
||||
@@ -72,7 +77,8 @@ qcom_setup_macs()
|
||||
|
||||
case $board in
|
||||
cig,wf194c|\
|
||||
cig,wf194c4)
|
||||
cig,wf194c4|\
|
||||
cig,wf196)
|
||||
mac=$(grep BaseMacAddress= /dev/mtd14 | cut -dx -f2)
|
||||
wan_mac=$(macaddr_canonicalize $mac)
|
||||
lan_mac=$(macaddr_add "$wan_mac" 1)
|
||||
@@ -80,6 +86,15 @@ qcom_setup_macs()
|
||||
ucidef_set_network_device_mac eth1 $wan_mac
|
||||
ucidef_set_label_macaddr $wan_mac
|
||||
;;
|
||||
cybertan,eww622-a1)
|
||||
mac=$(grep -i -m 1 mac_addr_base= /dev/`cat /proc/mtd | grep devinfo | cut -d: -f1` | cut -d= -f2)
|
||||
[ -z "$mac"] && mac="00:11:22:33:44:55"
|
||||
wan_mac=$(macaddr_canonicalize $mac)
|
||||
lan_mac=$(macaddr_add "$wan_mac" 1)
|
||||
ucidef_set_network_device_mac eth0 $wan_mac
|
||||
ucidef_set_network_device_mac eth1 $lan_mac
|
||||
ucidef_set_label_macaddr $wan_mac
|
||||
;;
|
||||
*)
|
||||
wan_mac=$(cat /sys/class/net/eth0/address)
|
||||
lan_mac=$(macaddr_add "$wan_mac" 1)
|
||||
@@ -87,11 +102,11 @@ qcom_setup_macs()
|
||||
esac
|
||||
[ -n "$lan_mac" ] && ucidef_set_interface_macaddr "lan" $lan_mac
|
||||
[ -n "$wan_mac" ] && ucidef_set_interface_macaddr "wan" $wan_mac
|
||||
[ -n "$wan_mac" ] && ucidef_set_label_macaddr "$wan_mac"
|
||||
}
|
||||
|
||||
board_config_update
|
||||
board=$(board_name)
|
||||
ucidef_set_bridge_device bridge
|
||||
qcom_setup_interfaces $board
|
||||
qcom_setup_macs $board
|
||||
board_config_flush
|
||||
|
||||
@@ -81,6 +81,7 @@ case "$FIRMWARE" in
|
||||
qcom,ipq807x-hk14|\
|
||||
tplink,ex227|\
|
||||
tplink,ex447|\
|
||||
yuncore,ax840|\
|
||||
sercomm,wallaby)
|
||||
caldata_extract "0:ART" 0x1000 0x20000
|
||||
;;
|
||||
@@ -96,7 +97,8 @@ case "$FIRMWARE" in
|
||||
wallys,dr6018|\
|
||||
wallys,dr6018-v4|\
|
||||
qcom,ipq6018-cp01|\
|
||||
xiaomi,ax1800)
|
||||
xiaomi,ax1800|\
|
||||
glinet,ax1800)
|
||||
caldata_extract "0:ART" 0x1000 0x20000
|
||||
;;
|
||||
esac
|
||||
@@ -104,11 +106,28 @@ case "$FIRMWARE" in
|
||||
ath11k/IPQ5018/hw1.0/caldata.bin)
|
||||
case "$board" in
|
||||
cybertan,eww622-a1|\
|
||||
edgecore,eap104|\
|
||||
motorola,q14|\
|
||||
qcom,ipq5018-mp03.1)
|
||||
caldata_extract "0:ART" 0x1000 0x20000
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
ath11k/qcn6122/hw1.0/caldata_1.bin)
|
||||
case "$board" in
|
||||
motorola,q14)
|
||||
caldata_extract "0:ART" 0x26800 0x20000
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
ath11k/qcn6122/hw1.0/caldata_2.bin)
|
||||
case "$board" in
|
||||
motorola,q14|\
|
||||
edgecore,eap104)
|
||||
caldata_extract "0:ART" 0x4c000 0x20000
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
ath11k/QCN9074/hw1.0/caldata_1.bin)
|
||||
case "$board" in
|
||||
cig,wf196|\
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
#!/bin/sh
|
||||
[ "$ACTION" = add ] || exit
|
||||
|
||||
NPROCS="$(grep -c "^processor.*:" /proc/cpuinfo)"
|
||||
[ "$NPROCS" -gt 1 ] || exit
|
||||
|
||||
PROC_MASK="$(( (1 << $NPROCS) - 1 ))"
|
||||
|
||||
find_irq_cpu() {
|
||||
local dev="$1"
|
||||
local match="$(grep -m 1 "$dev\$" /proc/interrupts)"
|
||||
local cpu=0
|
||||
|
||||
[ -n "$match" ] && {
|
||||
set -- $match
|
||||
shift
|
||||
for cur in `seq 1 $NPROCS`; do
|
||||
[ "$1" -gt 0 ] && {
|
||||
cpu=$(($cur - 1))
|
||||
break
|
||||
}
|
||||
shift
|
||||
done
|
||||
}
|
||||
|
||||
echo "$cpu"
|
||||
}
|
||||
|
||||
set_hex_val() {
|
||||
local file="$1"
|
||||
local val="$2"
|
||||
val="$(printf %x "$val")"
|
||||
[ -n "$DEBUG" ] && echo "$file = $val"
|
||||
echo "$val" > "$file"
|
||||
}
|
||||
|
||||
default_ps="$(uci get "network.@globals[0].default_ps")"
|
||||
[ -n "$default_ps" -a "$default_ps" != 1 ] && exit 0
|
||||
|
||||
exec 512>/var/lock/smp_tune.lock
|
||||
flock 512 || exit 1
|
||||
|
||||
for dev in /sys/class/net/*; do
|
||||
[ -d "$dev" ] || continue
|
||||
|
||||
# ignore virtual interfaces
|
||||
[ -n "$(ls "${dev}/" | grep '^lower_')" ] && continue
|
||||
[ -d "${dev}/device" ] || continue
|
||||
|
||||
device="$(readlink "${dev}/device")"
|
||||
device="$(basename "$device")"
|
||||
irq_cpu="$(find_irq_cpu "$device")"
|
||||
irq_cpu_mask="$((1 << $irq_cpu))"
|
||||
|
||||
for q in ${dev}/queues/rx-*; do
|
||||
set_hex_val "$q/rps_cpus" "$(($PROC_MASK & ~$irq_cpu_mask))"
|
||||
done
|
||||
|
||||
ntxq="$(ls -d ${dev}/queues/tx-* | wc -l)"
|
||||
|
||||
idx=$(($irq_cpu + 1))
|
||||
for q in ${dev}/queues/tx-*; do
|
||||
set_hex_val "$q/xps_cpus" "$((1 << $idx))"
|
||||
let "idx = idx + 1"
|
||||
[ "$idx" -ge "$NPROCS" ] && idx=0
|
||||
done
|
||||
done
|
||||
@@ -19,4 +19,12 @@ boot() {
|
||||
ssdk_sh debug phy set 8 0x4004c441 0x8
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$(board_name)" in
|
||||
cig,wf196)
|
||||
# setup the leds
|
||||
ssdk_sh debug phy set 0 0x401ec431 0xc00f
|
||||
ssdk_sh debug phy set 0 0x401ec430 0x806f
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
@@ -4,8 +4,14 @@ START=99
|
||||
|
||||
boot() {
|
||||
case "$(board_name)" in
|
||||
hfcl,ion4xe|\
|
||||
hfcl,ion4xi)
|
||||
fw_setenv boot_count 0
|
||||
;;
|
||||
edgecore,eap101|\
|
||||
edgecore,eap102)
|
||||
avail=$(fw_printenv -n upgrade_available)
|
||||
[ "${avail}" -eq 1 ] || fw_setenv upgrade_available 1
|
||||
fw_setenv bootcount 0
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
|
||||
START=80
|
||||
|
||||
set_affinity() {
|
||||
local affinity=$1
|
||||
local name=$2
|
||||
local irq=`grep -E -m1 $name /proc/interrupts | cut -d ':' -f 1 | tail -n1 | tr -d ' '`
|
||||
[ -n "$irq" ] && {
|
||||
logger ath11k setting affinity for $name/$irq to $affinity
|
||||
echo $affinity > /proc/irq/$irq/smp_affinity
|
||||
}
|
||||
}
|
||||
|
||||
boot() {
|
||||
. /lib/functions/system.sh
|
||||
|
||||
board=$(board_name)
|
||||
case $board in
|
||||
cig,wf196)
|
||||
set_affinity 1 reo2host-destination-ring2
|
||||
set_affinity 2 reo2host-destination-ring1
|
||||
;;
|
||||
*)
|
||||
set_affinity 2 reo2host-destination-ring2
|
||||
set_affinity 1 reo2host-destination-ring1
|
||||
;;
|
||||
esac
|
||||
|
||||
case $board in
|
||||
maple)
|
||||
;;
|
||||
*)
|
||||
set_affinity 8 reo2host-destination-ring4
|
||||
set_affinity 4 reo2host-destination-ring3
|
||||
|
||||
set_affinity 8 wbm2host-tx-completions-ring3
|
||||
set_affinity 4 wbm2host-tx-completions-ring2
|
||||
set_affinity 2 wbm2host-tx-completions-ring1
|
||||
|
||||
set_affinity 8 ppdu-end-interrupts-mac1
|
||||
set_affinity 8 rxdma2host-monitor-status-ring-mac1
|
||||
set_affinity 8 rxdma2host-monitor-destination-mac1
|
||||
set_affinity 8 host2rxdma-monitor-ring1
|
||||
;;
|
||||
esac
|
||||
|
||||
set_affinity 4 ppdu-end-interrupts-mac2
|
||||
set_affinity 4 rxdma2host-monitor-status-ring-mac2
|
||||
set_affinity 4 rxdma2host-monitor-destination-mac2
|
||||
set_affinity 4 host2rxdma-monitor-ring2
|
||||
|
||||
set_affinity 2 ppdu-end-interrupts-mac3
|
||||
set_affinity 2 rxdma2host-monitor-status-ring-mac3
|
||||
set_affinity 2 rxdma2host-monitor-destination-mac3
|
||||
set_affinity 2 host2rxdma-monitor-ring3
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
. /lib/functions/system.sh
|
||||
|
||||
RAMFS_COPY_BIN='fw_printenv fw_setenv'
|
||||
RAMFS_COPY_DATA='/etc/fw_env.config /var/lock/fw_printenv.lock'
|
||||
|
||||
qca_do_upgrade() {
|
||||
local tar_file="$1"
|
||||
|
||||
@@ -16,6 +19,50 @@ qca_do_upgrade() {
|
||||
fi
|
||||
}
|
||||
|
||||
find_mmc_part() {
|
||||
local DEVNAME PARTNAME
|
||||
|
||||
if grep -q "$1" /proc/mtd; then
|
||||
echo "" && return 0
|
||||
fi
|
||||
|
||||
for DEVNAME in /sys/block/mmcblk*/mmcblk*p*; do
|
||||
PARTNAME=$(grep PARTNAME ${DEVNAME}/uevent | cut -f2 -d'=')
|
||||
[ "$PARTNAME" = "$1" ] && echo "/dev/$(basename $DEVNAME)" && return 0
|
||||
done
|
||||
}
|
||||
|
||||
do_flash_emmc() {
|
||||
local tar_file=$1
|
||||
local emmcblock=$(find_mmc_part $2)
|
||||
local board_dir=$3
|
||||
local part=$4
|
||||
|
||||
[ -z "$emmcblock" ] && {
|
||||
echo failed to find $2
|
||||
return
|
||||
}
|
||||
|
||||
echo erase $4
|
||||
dd if=/dev/zero of=${emmcblock} 2> /dev/null
|
||||
echo flash $4
|
||||
tar Oxf $tar_file ${board_dir}/$part | dd of=${emmcblock}
|
||||
}
|
||||
|
||||
emmc_do_upgrade() {
|
||||
local tar_file="$1"
|
||||
|
||||
local board_dir=$(tar tf $tar_file | grep -m 1 '^sysupgrade-.*/$')
|
||||
board_dir=${board_dir%/}
|
||||
do_flash_emmc $tar_file '0:HLOS' $board_dir kernel
|
||||
do_flash_emmc $tar_file 'rootfs' $board_dir root
|
||||
|
||||
local emmcblock="$(find_mmc_part "rootfs_data")"
|
||||
if [ -e "$emmcblock" ]; then
|
||||
mkfs.ext4 -F "$emmcblock"
|
||||
fi
|
||||
}
|
||||
|
||||
platform_check_image() {
|
||||
local magic_long="$(get_magic_long "$1")"
|
||||
board=$(board_name)
|
||||
@@ -26,15 +73,20 @@ platform_check_image() {
|
||||
cig,wf194c4|\
|
||||
cig,wf196|\
|
||||
cybertan,eww622-a1|\
|
||||
glinet,ax1800|\
|
||||
glinet,axt1800|\
|
||||
wallys,dr6018|\
|
||||
wallys,dr6018-v4|\
|
||||
edgecore,eap101|\
|
||||
edgecore,eap102|\
|
||||
edgecore,eap104|\
|
||||
edgecore,eap106|\
|
||||
hfcl,ion4xi|\
|
||||
hfcl,ion4xe|\
|
||||
tplink,ex227|\
|
||||
tplink,ex447|\
|
||||
yuncore,ax840|\
|
||||
motorola,q14|\
|
||||
qcom,ipq6018-cp01|\
|
||||
qcom,ipq807x-hk01|\
|
||||
qcom,ipq807x-hk14|\
|
||||
@@ -55,29 +107,58 @@ platform_do_upgrade() {
|
||||
cig,wf188)
|
||||
qca_do_upgrade $1
|
||||
;;
|
||||
motorola,q14)
|
||||
emmc_do_upgrade $1
|
||||
;;
|
||||
cig,wf188n|\
|
||||
cig,wf194c|\
|
||||
cig,wf194c4|\
|
||||
cig,wf196|\
|
||||
cybertan,eww622-a1|\
|
||||
hfcl,ion4xi|\
|
||||
hfcl,ion4xe|\
|
||||
edgecore,eap104|\
|
||||
glinet,ax1800|\
|
||||
glinet,axt1800|\
|
||||
qcom,ipq6018-cp01|\
|
||||
qcom,ipq807x-hk01|\
|
||||
qcom,ipq807x-hk14|\
|
||||
qcom,ipq5018-mp03.3|\
|
||||
wallys,dr6018|\
|
||||
wallys,dr6018-v4|\
|
||||
yuncore,ax840|\
|
||||
tplink,ex447|\
|
||||
tplink,ex227)
|
||||
nand_upgrade_tar "$1"
|
||||
;;
|
||||
edgecore,eap106|\
|
||||
edgecore,eap102|\
|
||||
edgecore,eap101)
|
||||
hfcl,ion4xi|\
|
||||
hfcl,ion4xe)
|
||||
if grep -q rootfs_1 /proc/cmdline; then
|
||||
CI_UBIPART="rootfs"
|
||||
fw_setenv primary 0 || exit 1
|
||||
else
|
||||
CI_UBIPART="rootfs_1"
|
||||
fw_setenv primary 1 || exit 1
|
||||
fi
|
||||
nand_upgrade_tar "$1"
|
||||
;;
|
||||
edgecore,eap106)
|
||||
CI_UBIPART="rootfs1"
|
||||
[ "$(find_mtd_chardev rootfs)" ] && CI_UBIPART="rootfs"
|
||||
nand_upgrade_tar "$1"
|
||||
;;
|
||||
edgecore,eap101|\
|
||||
edgecore,eap102)
|
||||
if [ "$(find_mtd_chardev rootfs)" ]; then
|
||||
CI_UBIPART="rootfs"
|
||||
else
|
||||
if grep -q rootfs1 /proc/cmdline; then
|
||||
CI_UBIPART="rootfs2"
|
||||
fw_setenv active 2 || exit 1
|
||||
else
|
||||
CI_UBIPART="rootfs1"
|
||||
fw_setenv active 1 || exit 1
|
||||
fi
|
||||
fi
|
||||
nand_upgrade_tar "$1"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "../../../arm64/boot/dts/qcom/qcom-ipq5018-eap104.dts"
|
||||
|
||||
/ {
|
||||
pmuv8: pmu {
|
||||
compatible = "arm,cortex-a7-pmu";
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "../../../arm64/boot/dts/qcom/qcom-ipq5018-q14.dts"
|
||||
|
||||
/ {
|
||||
pmuv8: pmu {
|
||||
compatible = "arm,cortex-a7-pmu";
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2019, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "../../../arm64/boot/dts/qcom/qcom-ipq6018-gl-ax1800.dts"
|
||||
#include "qcom-ipq6018.dtsi"
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2019, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "../../../arm64/boot/dts/qcom/qcom-ipq6018-gl-axt1800.dts"
|
||||
#include "qcom-ipq6018.dtsi"
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2019, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "../../../arm64/boot/dts/qcom/qcom-ipq6018-yuncore-ax840.dts"
|
||||
#include "qcom-ipq6018.dtsi"
|
||||
1015
feeds/ipq807x/ipq807x/files/arch/arm64/boot/dts/qcom/qcom-ipq5018-eap104.dts
Executable file
1015
feeds/ipq807x/ipq807x/files/arch/arm64/boot/dts/qcom/qcom-ipq5018-eap104.dts
Executable file
File diff suppressed because it is too large
Load Diff
@@ -32,6 +32,10 @@
|
||||
serial1 = &blsp1_uart2;
|
||||
ethernet0 = "/soc/dp1";
|
||||
ethernet1 = "/soc/dp2";
|
||||
led-boot = &led_sys;
|
||||
led-failsafe = &led_sys;
|
||||
led-running = &led_sys;
|
||||
led-upgrade = &led_sys;
|
||||
};
|
||||
|
||||
chosen {
|
||||
@@ -708,32 +712,20 @@
|
||||
pinctrl-0 = <&leds_pins>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
led@1 {
|
||||
led_sys: led@1 {
|
||||
label = "sys:blue";
|
||||
gpios = <&tlmm 1 GPIO_ACTIVE_HIGH>; /* GPIO_1 */
|
||||
/* default-state="on"; */
|
||||
linux,default-trigger = "timer";
|
||||
active-delay = <700>;
|
||||
inactive-delay = <700>;
|
||||
default-state="on";
|
||||
};
|
||||
led@35 {
|
||||
label = "sys:green";
|
||||
gpios = <&tlmm 35 GPIO_ACTIVE_HIGH>; /* GPIO_35 */
|
||||
default-state="off";
|
||||
/* linux,default-trigger = "timer";
|
||||
active-delay = <700>;
|
||||
inactive-delay = <700>;
|
||||
default-state="on"; */
|
||||
};
|
||||
led@31 {
|
||||
label = "sys:red";
|
||||
gpios = <&tlmm 31 GPIO_ACTIVE_HIGH>; /* GPIO_31 */
|
||||
default-state="off";
|
||||
/* linux,default-trigger = "timer";
|
||||
active-delay = <700>;
|
||||
inactive-delay = <700>;
|
||||
default-state="on"; */
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
886
feeds/ipq807x/ipq807x/files/arch/arm64/boot/dts/qcom/qcom-ipq5018-q14.dts
Executable file
886
feeds/ipq807x/ipq807x/files/arch/arm64/boot/dts/qcom/qcom-ipq5018-q14.dts
Executable file
@@ -0,0 +1,886 @@
|
||||
/dts-v1/;
|
||||
/* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "qcom-ipq5018.dtsi"
|
||||
|
||||
/ {
|
||||
#address-cells = <0x2>;
|
||||
#size-cells = <0x2>;
|
||||
model = "Motorola Q14";
|
||||
compatible = "motorola,q14", "qcom,ipq5018-mp03.5-c1", "qcom,ipq5018";
|
||||
interrupt-parent = <&intc>;
|
||||
|
||||
aliases {
|
||||
sdhc1 = &sdhc_1; /* SDC1 eMMC slot */
|
||||
serial0 = &blsp1_uart1;
|
||||
serial1 = &blsp1_uart2;
|
||||
ethernet0 = "/soc/dp1";
|
||||
ethernet1 = "/soc/dp2";
|
||||
};
|
||||
|
||||
chosen {
|
||||
bootargs = "console=ttyMSM0,115200,n8 rw init=/init";
|
||||
#ifdef __IPQ_MEM_PROFILE_256_MB__
|
||||
bootargs-append = " swiotlb=1";
|
||||
#else
|
||||
bootargs-append = " swiotlb=1 coherent_pool=2M";
|
||||
#endif
|
||||
stdout-path = "serial0";
|
||||
};
|
||||
|
||||
reserved-memory {
|
||||
#ifdef __IPQ_MEM_PROFILE_256_MB__
|
||||
/* 256 MB Profile
|
||||
* +==========+==============+=========================+
|
||||
* | | | |
|
||||
* | Region | Start Offset | Size |
|
||||
* | | | |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | NSS | 0x40000000 | 8MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | Linux | 0x40800000 | Depends on total memory |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | uboot | 0x4A600000 | 4MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | SBL | 0x4AA00000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | smem | 0x4AB00000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | TZ | 0x4AC00000 | 4MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | Q6 | | |
|
||||
* | code/ | 0x4B000000 | 20MB |
|
||||
* | data | | |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | IPQ5018 | | |
|
||||
* | data | 0x4C400000 | 13MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | IPQ5018 | | |
|
||||
* | M3 Dump | 0x4D100000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | IPQ5018 | | |
|
||||
* | QDSS | 0x4D200000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_1| | |
|
||||
* | data | 0x4D300000 | 15MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_1| | |
|
||||
* | M3 Dump | 0x4E200000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_1| | |
|
||||
* | QDSS | 0x4E300000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_2| | |
|
||||
* | data | 0x4E400000 | 15MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_2| | |
|
||||
* | M3 Dump | 0x4F300000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_2| | |
|
||||
* | QDSS | 0x4F400000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | |
|
||||
* | Rest of the memory for Linux |
|
||||
* | |
|
||||
* +===================================================+
|
||||
*/
|
||||
q6_mem_regions: q6_mem_regions@4B000000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4B000000 0x0 0x4500000>;
|
||||
};
|
||||
|
||||
q6_code_data: q6_code_data@4B000000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4B000000 0x0 0x1400000>;
|
||||
};
|
||||
|
||||
q6_ipq5018_data: q6_ipq5018_data@4C400000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4C400000 0x0 0xD00000>;
|
||||
};
|
||||
|
||||
m3_dump: m3_dump@4D100000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4D100000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_etr_region: q6_etr_dump@4D200000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4D200000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_qcn6122_data1: q6_qcn6122_data1@4D300000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4D300000 0x0 0xF00000>;
|
||||
};
|
||||
|
||||
m3_dump_qcn6122_1: m3_dump_qcn6122_1@4E200000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4E200000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_qcn6122_etr_1: q6_qcn6122_etr_1@4E300000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4E300000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_qcn6122_data2: q6_qcn6122_data2@4E400000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4E400000 0x0 0xF00000>;
|
||||
};
|
||||
|
||||
m3_dump_qcn6122_2: m3_dump_qcn6122_2@4F300000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4F300000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_qcn6122_etr_2: q6_qcn6122_etr_2@4F400000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4F400000 0x0 0x100000>;
|
||||
};
|
||||
#else
|
||||
/* 512MB/1GB Profiles
|
||||
* +==========+==============+=========================+
|
||||
* | | | |
|
||||
* | Region | Start Offset | Size |
|
||||
* | | | |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | NSS | 0x40000000 | 16MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | Linux | 0x41000000 | Depends on total memory |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | uboot | 0x4A600000 | 4MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | SBL | 0x4AA00000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | smem | 0x4AB00000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | TZ | 0x4AC00000 | 4MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | Q6 | | |
|
||||
* | code/ | 0x4B000000 | 20MB |
|
||||
* | data | | |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | IPQ5018 | | |
|
||||
* | data | 0x4C400000 | 14MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | IPQ5018 | | |
|
||||
* | M3 Dump | 0x4D200000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | IPQ5018 | | |
|
||||
* | QDSS | 0x4D300000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | IPQ5018 | | |
|
||||
* | Caldb | 0x4D400000 | 2MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_1| | |
|
||||
* | data | 0x4D600000 | 16MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_1| | |
|
||||
* | M3 Dump | 0x4E600000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_1| | |
|
||||
* | QDSS | 0x4E700000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_1| | |
|
||||
* | Caldb | 0x4E800000 | 5MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_2| | |
|
||||
* | data | 0x4ED00000 | 16MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_2| | |
|
||||
* | M3 Dump | 0x4FD00000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_2| | |
|
||||
* | QDSS | 0x4FE00000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_2| | |
|
||||
* | Caldb | 0x4FF00000 | 5MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | |
|
||||
* | Rest of the memory for Linux |
|
||||
* | |
|
||||
* +===================================================+
|
||||
*/
|
||||
q6_mem_regions: q6_mem_regions@4B000000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4B000000 0x0 0x5400000>;
|
||||
};
|
||||
|
||||
q6_code_data: q6_code_data@4B000000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4B000000 0x0 01400000>;
|
||||
};
|
||||
|
||||
q6_ipq5018_data: q6_ipq5018_data@4C400000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4C400000 0x0 0xE00000>;
|
||||
};
|
||||
|
||||
m3_dump: m3_dump@4D200000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4D200000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_etr_region: q6_etr_dump@4D300000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4D300000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_caldb_region: q6_caldb_region@4D400000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4D400000 0x0 0x200000>;
|
||||
};
|
||||
|
||||
q6_qcn6122_data1: q6_qcn6122_data1@4D600000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4D600000 0x0 0x1000000>;
|
||||
};
|
||||
|
||||
m3_dump_qcn6122_1: m3_dump_qcn6122_1@4E600000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4E600000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_qcn6122_etr_1: q6_qcn6122_etr_1@4E700000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4E700000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_qcn6122_caldb_1: q6_qcn6122_caldb_1@4E800000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4E800000 0x0 0x500000>;
|
||||
};
|
||||
|
||||
q6_qcn6122_data2: q6_qcn6122_data2@4E900000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4ED00000 0x0 0x1000000>;
|
||||
};
|
||||
|
||||
m3_dump_qcn6122_2: m3_dump_qcn6122_2@4FD00000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4FD00000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_qcn6122_etr_2: q6_qcn6122_etr_2@4FE00000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4FE00000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_qcn6122_caldb_2: q6_qcn6122_caldb_2@4FF00000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4FF00000 0x0 0x500000>;
|
||||
};
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
soc {
|
||||
serial@78af000 {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
blsp1_uart2: serial@78b0000 {
|
||||
pinctrl-0 = <&blsp1_uart_pins>;
|
||||
pinctrl-names = "default";
|
||||
};
|
||||
|
||||
qpic_bam: dma@7984000{
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
nand: qpic-nand@79b0000 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
spi_0: spi@78b5000 { /* BLSP1 QUP0 */
|
||||
pinctrl-0 = <&blsp0_spi_pins>;
|
||||
pinctrl-names = "default";
|
||||
cs-select = <0>;
|
||||
status = "ok";
|
||||
|
||||
m25p80@0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
reg = <0>;
|
||||
compatible = "n25q128a11";
|
||||
linux,modalias = "m25p80", "n25q128a11";
|
||||
spi-max-frequency = <50000000>;
|
||||
use-default-sizes;
|
||||
};
|
||||
};
|
||||
|
||||
mdio0: mdio@88000 {
|
||||
status = "ok";
|
||||
|
||||
ethernet-phy@0 {
|
||||
reg = <7>;
|
||||
};
|
||||
};
|
||||
|
||||
mdio1: mdio@90000 {
|
||||
status = "ok";
|
||||
pinctrl-0 = <&mdio1_pins>;
|
||||
pinctrl-names = "default";
|
||||
phy-reset-gpio = <&tlmm 39 0>;
|
||||
|
||||
ethernet-phy@0 {
|
||||
reg = <28>;
|
||||
};
|
||||
};
|
||||
|
||||
ess-instance {
|
||||
num_devices = <0x1>;
|
||||
ess-switch@0x39c00000 {
|
||||
switch_mac_mode = <0xf>; /* mac mode for uniphy instance*/
|
||||
cmnblk_clk = "internal_96MHz"; /* cmnblk clk*/
|
||||
qcom,port_phyinfo {
|
||||
port@0 {
|
||||
port_id = <1>;
|
||||
phy_address = <7>;
|
||||
mdiobus = <&mdio0>;
|
||||
};
|
||||
port@1 {
|
||||
port_id = <2>;
|
||||
phy_address = <0x1c>;
|
||||
mdiobus = <&mdio1>;
|
||||
port_mac_sel = "QGMAC_PORT";
|
||||
};
|
||||
};
|
||||
led_source@0 {
|
||||
source = <0>;
|
||||
mode = "normal";
|
||||
speed = "all";
|
||||
blink_en = "enable";
|
||||
active = "high";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
dp1 {
|
||||
device_type = "network";
|
||||
compatible = "qcom,nss-dp";
|
||||
clocks = <&gcc GCC_SNOC_GMAC0_AXI_CLK>;
|
||||
clock-names = "nss-snoc-gmac-axi-clk";
|
||||
qcom,id = <1>;
|
||||
reg = <0x39C00000 0x10000>;
|
||||
interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
|
||||
qcom,mactype = <2>;
|
||||
qcom,link-poll = <1>;
|
||||
qcom,phy-mdio-addr = <7>;
|
||||
mdio-bus = <&mdio0>;
|
||||
local-mac-address = [000000000000];
|
||||
phy-mode = "sgmii";
|
||||
};
|
||||
|
||||
dp2 {
|
||||
device_type = "network";
|
||||
compatible = "qcom,nss-dp";
|
||||
clocks = <&gcc GCC_SNOC_GMAC1_AXI_CLK>;
|
||||
clock-names = "nss-snoc-gmac-axi-clk";
|
||||
qcom,id = <2>;
|
||||
reg = <0x39D00000 0x10000>;
|
||||
interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
|
||||
qcom,mactype = <2>;
|
||||
qcom,link-poll = <1>;
|
||||
qcom,phy-mdio-addr = <28>;
|
||||
mdio-bus = <&mdio1>;
|
||||
local-mac-address = [000000000000];
|
||||
phy-mode = "sgmii";
|
||||
};
|
||||
|
||||
qcom,test@0 {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
nss-macsec1 {
|
||||
compatible = "qcom,nss-macsec";
|
||||
phy_addr = <0x1c>;
|
||||
mdiobus = <&mdio1>;
|
||||
};
|
||||
|
||||
lpass: lpass@0xA000000{
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
pcm: pcm@0xA3C0000{
|
||||
pinctrl-0 = <&audio_pins>;
|
||||
pinctrl-names = "default";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
pcm_lb: pcm_lb@0 {
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
||||
thermal-zones {
|
||||
status = "ok";
|
||||
};
|
||||
};
|
||||
|
||||
&sdhc_1 {
|
||||
pinctrl-0 = <&emmc_pins>;
|
||||
pinctrl-names = "default";
|
||||
qcom,clk-rates = <400000 25000000 50000000 100000000 \
|
||||
192000000 384000000>;
|
||||
qcom,bus-speed-mode = "HS200_1p8v", "DDR_1p8v";
|
||||
qcom,nonremovable;
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&tlmm {
|
||||
pinctrl-0 = <&blsp0_uart_pins &phy_led_pins>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
blsp0_uart_pins: uart_pins {
|
||||
blsp0_uart_rx_tx {
|
||||
pins = "gpio20", "gpio21";
|
||||
function = "blsp0_uart0";
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
|
||||
blsp1_uart_pins: blsp1_uart_pins {
|
||||
blsp1_uart_rx_tx {
|
||||
pins = "gpio23", "gpio25", "gpio24", "gpio26";
|
||||
function = "blsp1_uart2";
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
|
||||
blsp0_spi_pins: blsp0_spi_pins {
|
||||
mux {
|
||||
pins = "gpio10", "gpio11", "gpio12", "gpio13";
|
||||
function = "blsp0_spi";
|
||||
drive-strength = <2>;
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
|
||||
emmc_pins: emmc_pins {
|
||||
emmc_clk {
|
||||
pins = "gpio9";
|
||||
function = "sdc1_clk";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
emmc_cmd {
|
||||
pins = "gpio8";
|
||||
function = "sdc1_cmd";
|
||||
drive-strength = <8>;
|
||||
bias-pull-up;
|
||||
};
|
||||
emmc_data_0 {
|
||||
pins = "gpio7";
|
||||
function = "sdc10";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
emmc_data_1 {
|
||||
pins = "gpio6";
|
||||
function = "sdc11";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
emmc_data_2 {
|
||||
pins = "gpio5";
|
||||
function = "sdc12";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
emmc_data_3 {
|
||||
pins = "gpio4";
|
||||
function = "sdc13";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
|
||||
mdio1_pins: mdio_pinmux {
|
||||
mux_0 {
|
||||
pins = "gpio36";
|
||||
function = "mdc";
|
||||
drive-strength = <8>;
|
||||
bias-pull-up;
|
||||
};
|
||||
|
||||
mux_1 {
|
||||
pins = "gpio37";
|
||||
function = "mdio";
|
||||
drive-strength = <8>;
|
||||
bias-pull-up;
|
||||
};
|
||||
};
|
||||
|
||||
phy_led_pins: phy_led_pins {
|
||||
gephy_led_pin {
|
||||
pins = "gpio46";
|
||||
function = "led0";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
};
|
||||
|
||||
i2c_pins: i2c_pins {
|
||||
i2c_scl {
|
||||
pins = "gpio25";
|
||||
function = "blsp2_i2c1";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
|
||||
i2c_sda {
|
||||
pins = "gpio26";
|
||||
function = "blsp2_i2c1";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
|
||||
button_pins: button_pins {
|
||||
wps_button {
|
||||
pins = "gpio38";
|
||||
function = "gpio";
|
||||
drive-strength = <8>;
|
||||
bias-pull-up;
|
||||
};
|
||||
|
||||
reset_button {
|
||||
pins = "gpio31";
|
||||
function = "gpio";
|
||||
drive-strength = <8>;
|
||||
bias-pull-up;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
audio_pins: audio_pinmux {
|
||||
mux_1 {
|
||||
pins = "gpio24";
|
||||
function = "audio_rxbclk";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
|
||||
mux_2 {
|
||||
pins = "gpio25";
|
||||
function = "audio_rxfsync";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
|
||||
mux_3 {
|
||||
pins = "gpio26";
|
||||
function = "audio_rxd";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
|
||||
mux_4 {
|
||||
pins = "gpio27";
|
||||
function = "audio_txmclk";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
|
||||
mux_5 {
|
||||
pins = "gpio28";
|
||||
function = "audio_txbclk";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
|
||||
mux_6 {
|
||||
pins = "gpio29";
|
||||
function = "audio_txfsync";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
|
||||
mux_7 {
|
||||
pins = "gpio30";
|
||||
function = "audio_txd";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
&soc {
|
||||
gpio_keys {
|
||||
compatible = "gpio-keys";
|
||||
pinctrl-0 = <&button_pins>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
button@1 {
|
||||
label = "wps";
|
||||
linux,code = <KEY_WPS_BUTTON>;
|
||||
gpios = <&tlmm 38 GPIO_ACTIVE_LOW>;
|
||||
linux,input-type = <1>;
|
||||
debounce-interval = <60>;
|
||||
};
|
||||
|
||||
button@2 {
|
||||
label = "reset";
|
||||
linux,code = <KEY_RESTART>;
|
||||
gpios = <&tlmm 31 GPIO_ACTIVE_LOW>;
|
||||
linux,input-type = <1>;
|
||||
debounce-interval = <60>;
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
&usb3 {
|
||||
status = "ok";
|
||||
device-power-gpio = <&tlmm 24 1>;
|
||||
};
|
||||
|
||||
&eud {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&pcie_x1 {
|
||||
status = "ok";
|
||||
perst-gpio = <&tlmm 18 1>;
|
||||
};
|
||||
|
||||
&pcie_x2 {
|
||||
status = "ok";
|
||||
perst-gpio = <&tlmm 15 1>;
|
||||
};
|
||||
|
||||
&dwc_0 {
|
||||
/delete-property/ #phy-cells;
|
||||
/delete-property/ phys;
|
||||
/delete-property/ phy-names;
|
||||
};
|
||||
|
||||
&hs_m31phy_0 {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&pcie_x1phy {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&pcie_x2phy {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&pcie_x1_rp {
|
||||
status = "ok";
|
||||
|
||||
mhi_0: qcom,mhi@0 {
|
||||
reg = <0 0 0 0 0 >;
|
||||
};
|
||||
};
|
||||
|
||||
&pcie_x2_rp {
|
||||
status = "ok";
|
||||
|
||||
mhi_1: qcom,mhi@1 {
|
||||
reg = <0 0 0 0 0 >;
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
&qfprom {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&tsens {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&qcom_q6v5_wcss {
|
||||
qcom,multipd_arch;
|
||||
memory-region = <&q6_mem_regions>;
|
||||
qcom,share_bootargs;
|
||||
qcom,bootargs_smem = <507>;
|
||||
boot-args = <0x1 0x4 0x3 0x0F 0x0 0x0>,
|
||||
<0x2 0x4 0x2 0x12 0x0 0x0>;
|
||||
|
||||
/* IPQ5018 */
|
||||
q6v5_wcss_userpd1 {
|
||||
m3_firmware = "IPQ5018/m3_fw.mdt";
|
||||
interrupts-extended = <&wcss_smp2p_in 8 0>,
|
||||
<&wcss_smp2p_in 9 0>,
|
||||
<&wcss_smp2p_in 12 0>,
|
||||
<&wcss_smp2p_in 11 0>;
|
||||
interrupt-names ="fatal",
|
||||
"ready",
|
||||
"spawn_ack",
|
||||
"stop-ack";
|
||||
qcom,smem-states = <&wcss_smp2p_out 8>,
|
||||
<&wcss_smp2p_out 9>,
|
||||
<&wcss_smp2p_out 10>;
|
||||
qcom,smem-state-names = "shutdown",
|
||||
"stop",
|
||||
"spawn";
|
||||
qca,asid = <1>;
|
||||
qca,auto-restart;
|
||||
qca,int_radio;
|
||||
#ifdef __IPQ_MEM_PROFILE_256_MB__
|
||||
memory-region = <&q6_ipq5018_data>, <&m3_dump>,
|
||||
<&q6_etr_region>;
|
||||
#else
|
||||
memory-region = <&q6_ipq5018_data>, <&m3_dump>,
|
||||
<&q6_etr_region>, <&q6_caldb_region>;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* QCN6122 6G */
|
||||
q6v5_wcss_userpd2 {
|
||||
m3_firmware = "qcn6122/m3_fw.mdt";
|
||||
interrupts-extended = <&wcss_smp2p_in 16 0>,
|
||||
<&wcss_smp2p_in 17 0>,
|
||||
<&wcss_smp2p_in 20 0>,
|
||||
<&wcss_smp2p_in 19 0>;
|
||||
interrupt-names ="fatal",
|
||||
"ready",
|
||||
"spawn_ack",
|
||||
"stop-ack";
|
||||
qcom,smem-states = <&wcss_smp2p_out 16>,
|
||||
<&wcss_smp2p_out 17>,
|
||||
<&wcss_smp2p_out 18>;
|
||||
qcom,smem-state-names = "shutdown",
|
||||
"stop",
|
||||
"spawn";
|
||||
qca,asid = <2>;
|
||||
qca,auto-restart;
|
||||
#ifdef __IPQ_MEM_PROFILE_256_MB__
|
||||
memory-region = <&q6_qcn6122_data1>, <&m3_dump_qcn6122_1>,
|
||||
<&q6_qcn6122_etr_1>;
|
||||
#else
|
||||
memory-region = <&q6_qcn6122_data1>, <&m3_dump_qcn6122_1>,
|
||||
<&q6_qcn6122_etr_1>, <&q6_qcn6122_caldb_1>;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* QCN6122 5G */
|
||||
q6v5_wcss_userpd3 {
|
||||
m3_firmware = "qcn6122/m3_fw.mdt";
|
||||
interrupts-extended = <&wcss_smp2p_in 24 0>,
|
||||
<&wcss_smp2p_in 25 0>,
|
||||
<&wcss_smp2p_in 28 0>,
|
||||
<&wcss_smp2p_in 27 0>;
|
||||
interrupt-names ="fatal",
|
||||
"ready",
|
||||
"spawn_ack",
|
||||
"stop-ack";
|
||||
qcom,smem-states = <&wcss_smp2p_out 24>,
|
||||
<&wcss_smp2p_out 25>,
|
||||
<&wcss_smp2p_out 26>;
|
||||
qcom,smem-state-names = "shutdown",
|
||||
"stop",
|
||||
"spawn";
|
||||
qca,asid = <3>;
|
||||
qca,auto-restart;
|
||||
#ifdef __IPQ_MEM_PROFILE_256_MB__
|
||||
memory-region = <&q6_qcn6122_data2>, <&m3_dump_qcn6122_2>,
|
||||
<&q6_qcn6122_etr_2>;
|
||||
#else
|
||||
memory-region = <&q6_qcn6122_data2>, <&m3_dump_qcn6122_2>,
|
||||
<&q6_qcn6122_etr_2>, <&q6_qcn6122_caldb_2>;
|
||||
#endif
|
||||
};
|
||||
};
|
||||
|
||||
&i2c_0 {
|
||||
pinctrl-0 = <&i2c_pins>;
|
||||
pinctrl-names = "default";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&qgic_msi_0 {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&qgic_msi_1 {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&wifi0 {
|
||||
/* IPQ5018 */
|
||||
qcom,multipd_arch;
|
||||
qcom,userpd-subsys-name = "q6v5_wcss_userpd1";
|
||||
#ifdef __IPQ_MEM_PROFILE_256_MB__
|
||||
qcom,tgt-mem-mode = <2>;
|
||||
#else
|
||||
qcom,tgt-mem-mode = <1>;
|
||||
#endif
|
||||
qcom,board_id = <0x24>;
|
||||
qcom,bdf-addr = <0x4C400000 0x4C400000 0x4C400000 0x0 0x0>;
|
||||
#ifdef __CNSS2__
|
||||
qcom,caldb-addr = <0x4D400000 0x4D400000 0 0 0>;
|
||||
#else
|
||||
qcom,caldb-addr = <0x4D400000>;
|
||||
m3-dump-addr = <0x4D200000>;
|
||||
nss-radio-priority = <0>;
|
||||
#endif
|
||||
mem-region = <&q6_ipq5018_data>;
|
||||
qcom,caldb-size = <0x200000>;
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&wifi1 {
|
||||
/* QCN6122 5G */
|
||||
qcom,multipd_arch;
|
||||
qcom,userpd-subsys-name = "q6v5_wcss_userpd2";
|
||||
#ifdef __IPQ_MEM_PROFILE_256_MB__
|
||||
qcom,tgt-mem-mode = <2>;
|
||||
#else
|
||||
qcom,tgt-mem-mode = <1>;
|
||||
#endif
|
||||
qcom,board_id = <0x60>;
|
||||
qcom,bdf-addr = <0x4D600000 0x4D600000 0x4D300000 0x0 0x0>;
|
||||
#ifdef __CNSS2__
|
||||
qcom,caldb-addr = <0x4E800000 0x4E800000 0 0 0>;
|
||||
#else
|
||||
qcom,caldb-addr = <0x4E800000>;
|
||||
m3-dump-addr = <0x4E600000>;
|
||||
nss-radio-priority = <1>;
|
||||
#endif
|
||||
mem-region = <&q6_qcn6122_data1>;
|
||||
qcom,caldb-size = <0x500000>;
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&wifi2 {
|
||||
/* QCN6122 6G */
|
||||
qcom,multipd_arch;
|
||||
qcom,userpd-subsys-name = "q6v5_wcss_userpd3";
|
||||
#ifdef __IPQ_MEM_PROFILE_256_MB__
|
||||
qcom,tgt-mem-mode = <2>;
|
||||
#else
|
||||
qcom,tgt-mem-mode = <1>;
|
||||
#endif
|
||||
qcom,board_id = <0xb0>;
|
||||
qcom,bdf-addr = <0x4ED00000 0x4ED00000 0x4E400000 0x0 0x0>;
|
||||
#ifdef __CNSS2__
|
||||
qcom,caldb-addr = <0x4FF00000 0x4FF00000 0 0 0>;
|
||||
#else
|
||||
qcom,caldb-addr = <0x4FF00000>;
|
||||
m3-dump-addr = <0x4FD00000>;
|
||||
nss-radio-priority = <1>;
|
||||
#endif
|
||||
mem-region = <&q6_qcn6122_data2>;
|
||||
qcom,caldb-size = <0x500000>;
|
||||
status = "ok";
|
||||
};
|
||||
@@ -0,0 +1,78 @@
|
||||
/dts-v1/;
|
||||
/*
|
||||
* Copyright (c) 2019, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "qcom-ipq6018-gl-ax1800.dtsi"
|
||||
|
||||
/ {
|
||||
model = "GL Technologies, Inc. AX1800";
|
||||
compatible = "glinet,ax1800", "qcom,ipq6018-cp03", "qcom,ipq6018";
|
||||
|
||||
aliases {
|
||||
ethernet3 = "/soc/dp4";
|
||||
ethernet4 = "/soc/dp5";
|
||||
};
|
||||
};
|
||||
|
||||
&mdio0 {
|
||||
phy3: ethernet-phy@3 {
|
||||
reg = <3>;
|
||||
};
|
||||
phy4: ethernet-phy@4 {
|
||||
reg = <4>;
|
||||
};
|
||||
};
|
||||
|
||||
&ess0 {
|
||||
switch_lan_bmp = <0x3c>; /* lan port bitmap */
|
||||
|
||||
qcom,port_phyinfo {
|
||||
port@3 {
|
||||
port_id = <4>;
|
||||
phy_address = <3>;
|
||||
};
|
||||
port@4 {
|
||||
port_id = <5>;
|
||||
phy_address = <4>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&soc {
|
||||
dp4 {
|
||||
device_type = "network";
|
||||
compatible = "qcom,nss-dp";
|
||||
qcom,id = <4>;
|
||||
reg = <0x3a001600 0x200>;
|
||||
qcom,mactype = <0>;
|
||||
local-mac-address = [000000000000];
|
||||
qcom,link-poll = <1>;
|
||||
qcom,phy-mdio-addr = <3>;
|
||||
phy-mode = "sgmii";
|
||||
};
|
||||
|
||||
dp5 {
|
||||
device_type = "network";
|
||||
compatible = "qcom,nss-dp";
|
||||
qcom,id = <5>;
|
||||
reg = <0x3a001800 0x200>;
|
||||
qcom,mactype = <0>;
|
||||
local-mac-address = [000000000000];
|
||||
qcom,link-poll = <1>;
|
||||
qcom,phy-mdio-addr = <4>;
|
||||
phy-mode = "sgmii";
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,364 @@
|
||||
/*
|
||||
* Copyright (c) 2019, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "qcom-ipq6018.dtsi"
|
||||
#include <dt-bindings/input/input.h>
|
||||
|
||||
/ {
|
||||
#address-cells = <0x2>;
|
||||
#size-cells = <0x2>;
|
||||
interrupt-parent = <&intc>;
|
||||
qcom,msm-id = <0x1A5 0x0>;
|
||||
|
||||
aliases {
|
||||
ethernet0 = "/soc/dp1";
|
||||
ethernet1 = "/soc/dp2";
|
||||
ethernet2 = "/soc/dp3";
|
||||
|
||||
led-boot = &led_run;
|
||||
led-failsafe = &led_run;
|
||||
led-running = &led_run;
|
||||
led-upgrade = &led_run;
|
||||
};
|
||||
|
||||
chosen {
|
||||
bootargs = "console=ttyMSM0,115200,n8 rw init=/init";
|
||||
bootargs-append = " swiotlb=1 coherent_pool=2M";
|
||||
};
|
||||
};
|
||||
|
||||
&tlmm {
|
||||
uart_pins: uart_pins {
|
||||
mux {
|
||||
pins = "gpio44", "gpio45";
|
||||
function = "blsp2_uart";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
};
|
||||
|
||||
qpic_pins: qpic_pins {
|
||||
data_0 {
|
||||
pins = "gpio15";
|
||||
function = "qpic_pad0";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
data_1 {
|
||||
pins = "gpio12";
|
||||
function = "qpic_pad1";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
data_2 {
|
||||
pins = "gpio13";
|
||||
function = "qpic_pad2";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
data_3 {
|
||||
pins = "gpio14";
|
||||
function = "qpic_pad3";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
data_4 {
|
||||
pins = "gpio5";
|
||||
function = "qpic_pad4";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
data_5 {
|
||||
pins = "gpio6";
|
||||
function = "qpic_pad5";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
data_6 {
|
||||
pins = "gpio7";
|
||||
function = "qpic_pad6";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
data_7 {
|
||||
pins = "gpio8";
|
||||
function = "qpic_pad7";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
qpic_pad {
|
||||
pins = "gpio1", "gpio3", "gpio4",
|
||||
"gpio10", "gpio11", "gpio17";
|
||||
function = "qpic_pad";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
};
|
||||
|
||||
button_pins: button_pins {
|
||||
switch_button {
|
||||
pins = "gpio9";
|
||||
function = "gpio";
|
||||
drive-strength = <8>;
|
||||
bias-pull-up;
|
||||
};
|
||||
reset_button {
|
||||
pins = "gpio18";
|
||||
function = "gpio";
|
||||
drive-strength = <8>;
|
||||
bias-pull-up;
|
||||
};
|
||||
};
|
||||
|
||||
mdio_pins: mdio_pinmux {
|
||||
mux_0 {
|
||||
pins = "gpio64";
|
||||
function = "mdc";
|
||||
drive-strength = <8>;
|
||||
bias-pull-up;
|
||||
};
|
||||
mux_1 {
|
||||
pins = "gpio65";
|
||||
function = "mdio";
|
||||
drive-strength = <8>;
|
||||
bias-pull-up;
|
||||
};
|
||||
mux_2 {
|
||||
pins = "gpio74";
|
||||
function = "gpio";
|
||||
bias-pull-up;
|
||||
};
|
||||
};
|
||||
|
||||
leds_pins: leds_pins {
|
||||
white {
|
||||
pins = "gpio35";
|
||||
function = "gpio";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
blue {
|
||||
pins = "gpio37";
|
||||
function = "gpio";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
};
|
||||
|
||||
usb_pins: usb_pins {
|
||||
usb_pwr {
|
||||
pins = "gpio0";
|
||||
function = "gpio";
|
||||
bias-pull-up;
|
||||
output-high;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&soc {
|
||||
mdio0: mdio@90000 {
|
||||
pinctrl-0 = <&mdio_pins>;
|
||||
pinctrl-names = "default";
|
||||
phy-reset-gpio = <&tlmm 74 GPIO_ACTIVE_HIGH>;
|
||||
status = "ok";
|
||||
phy0: ethernet-phy@0 {
|
||||
reg = <0>;
|
||||
};
|
||||
phy1: ethernet-phy@1 {
|
||||
reg = <1>;
|
||||
};
|
||||
phy2: ethernet-phy@2 {
|
||||
reg = <2>;
|
||||
};
|
||||
};
|
||||
|
||||
ess0: ess-switch@3a000000 {
|
||||
switch_cpu_bmp = <0x1>; /* cpu port bitmap */
|
||||
switch_lan_bmp = <0x0c>; /* lan port bitmap */
|
||||
switch_wan_bmp = <0x02>; /* wan port bitmap */
|
||||
switch_inner_bmp = <0xc0>; /*inner port bitmap*/
|
||||
switch_mac_mode = <0x0>; /* mac mode for uniphy instance0*/
|
||||
switch_mac_mode1 = <0xff>; /* mac mode for uniphy instance1*/
|
||||
switch_mac_mode2 = <0xff>; /* mac mode for uniphy instance2*/
|
||||
qcom,port_phyinfo {
|
||||
port@0 {
|
||||
port_id = <1>;
|
||||
phy_address = <0>;
|
||||
};
|
||||
port@1 {
|
||||
port_id = <2>;
|
||||
phy_address = <1>;
|
||||
};
|
||||
port@2 {
|
||||
port_id = <3>;
|
||||
phy_address = <2>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
dp1 {
|
||||
device_type = "network";
|
||||
compatible = "qcom,nss-dp";
|
||||
qcom,id = <1>;
|
||||
reg = <0x3a001000 0x200>;
|
||||
qcom,mactype = <0>;
|
||||
local-mac-address = [000000000000];
|
||||
qcom,link-poll = <1>;
|
||||
qcom,phy-mdio-addr = <0>;
|
||||
phy-mode = "sgmii";
|
||||
};
|
||||
|
||||
dp2 {
|
||||
device_type = "network";
|
||||
compatible = "qcom,nss-dp";
|
||||
qcom,id = <2>;
|
||||
reg = <0x3a001200 0x200>;
|
||||
qcom,mactype = <0>;
|
||||
local-mac-address = [000000000000];
|
||||
qcom,link-poll = <1>;
|
||||
qcom,phy-mdio-addr = <1>;
|
||||
phy-mode = "sgmii";
|
||||
};
|
||||
|
||||
dp3 {
|
||||
device_type = "network";
|
||||
compatible = "qcom,nss-dp";
|
||||
qcom,id = <3>;
|
||||
reg = <0x3a001400 0x200>;
|
||||
qcom,mactype = <0>;
|
||||
local-mac-address = [000000000000];
|
||||
qcom,link-poll = <1>;
|
||||
qcom,phy-mdio-addr = <2>;
|
||||
phy-mode = "sgmii";
|
||||
};
|
||||
|
||||
leds {
|
||||
compatible = "gpio-leds";
|
||||
pinctrl-0 = <&leds_pins>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
led_run: led@35 {
|
||||
label = "white:sys";
|
||||
gpios = <&tlmm 35 GPIO_ACTIVE_HIGH>;
|
||||
default-state = "on";
|
||||
};
|
||||
|
||||
led@37 {
|
||||
label = "blue:wan";
|
||||
gpios = <&tlmm 37 GPIO_ACTIVE_HIGH>;
|
||||
default-state = "on";
|
||||
};
|
||||
};
|
||||
|
||||
gpio_keys {
|
||||
compatible = "gpio-keys";
|
||||
pinctrl-0 = <&button_pins>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
switch {
|
||||
label = "switch";
|
||||
linux,code = <KEY_WPS_BUTTON>;
|
||||
gpios = <&tlmm 9 GPIO_ACTIVE_LOW>;
|
||||
linux,input-type = <1>;
|
||||
debounce-interval = <60>;
|
||||
};
|
||||
reset {
|
||||
label = "reset";
|
||||
linux,code = <KEY_RESTART>;
|
||||
gpios = <&tlmm 18 GPIO_ACTIVE_LOW>;
|
||||
linux,input-type = <1>;
|
||||
debounce-interval = <60>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&blsp1_uart3 {
|
||||
pinctrl-0 = <&uart_pins>;
|
||||
pinctrl-names = "default";
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&qpic_bam {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&nand {
|
||||
pinctrl-0 = <&qpic_pins>;
|
||||
pinctrl-names = "default";
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&ssphy_0 {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&qusb_phy_0 {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&usb3 {
|
||||
pinctrl-0 = <&usb_pins>;
|
||||
pinctrl-names = "default";
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&nss_crypto {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&q6_region {
|
||||
reg = <0x0 0x4ab00000 0x0 0x05500000>;
|
||||
};
|
||||
|
||||
&CPU0 {
|
||||
operating-points = <
|
||||
/* kHz uV (fixed) */
|
||||
864000 1100000
|
||||
1056000 1100000
|
||||
1200000 1100000
|
||||
>;
|
||||
clock-latency = <200000>;
|
||||
};
|
||||
|
||||
&CPU1 {
|
||||
operating-points = <
|
||||
/* kHz uV (fixed) */
|
||||
864000 1100000
|
||||
1056000 1100000
|
||||
1200000 1100000
|
||||
>;
|
||||
clock-latency = <200000>;
|
||||
};
|
||||
|
||||
&CPU2 {
|
||||
operating-points = <
|
||||
/* kHz uV (fixed) */
|
||||
864000 1100000
|
||||
1056000 1100000
|
||||
1200000 1100000
|
||||
>;
|
||||
clock-latency = <200000>;
|
||||
};
|
||||
|
||||
&CPU3 {
|
||||
operating-points = <
|
||||
/* kHz uV (fixed) */
|
||||
864000 1100000
|
||||
1056000 1100000
|
||||
1200000 1100000
|
||||
>;
|
||||
clock-latency = <200000>;
|
||||
};
|
||||
@@ -0,0 +1,94 @@
|
||||
/dts-v1/;
|
||||
/*
|
||||
* Copyright (c) 2019, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "qcom-ipq6018-gl-ax1800.dtsi"
|
||||
|
||||
/ {
|
||||
model = "GL Technologies, Inc. AXT1800";
|
||||
compatible = "glinet,axt1800", "qcom,ipq6018-cp03", "qcom,ipq6018";
|
||||
|
||||
aliases {
|
||||
sdhc0 = &sdhc_2;
|
||||
};
|
||||
};
|
||||
|
||||
&tlmm {
|
||||
sd_pins: sd_pins {
|
||||
sd {
|
||||
pins = "gpio62";
|
||||
function = "sd_card";
|
||||
bias-pull-up;
|
||||
};
|
||||
ldo {
|
||||
pins = "gpio66";
|
||||
function = "gpio";
|
||||
bias-pull-up;
|
||||
};
|
||||
};
|
||||
|
||||
pwm_pins: pwm_pinmux {
|
||||
pwm {
|
||||
pins = "gpio30";
|
||||
function = "pwm13";
|
||||
drive-strength = <8>;
|
||||
};
|
||||
};
|
||||
|
||||
fan_pins: fan_pins {
|
||||
pwr {
|
||||
pins = "gpio29";
|
||||
function = "gpio";
|
||||
bias-pull-up;
|
||||
output-high;
|
||||
};
|
||||
speed {
|
||||
pins = "gpio31";
|
||||
function = "gpio";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&soc {
|
||||
pwm:pwm {
|
||||
#pwm-cells = <2>;
|
||||
pinctrl-0 = <&pwm_pins>;
|
||||
pinctrl-names = "default";
|
||||
used-pwm-indices = <0>, <1>, <0>, <0>;
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
pwm-fan {
|
||||
compatible = "pwm-fan";
|
||||
pinctrl-0 = <&fan_pins>;
|
||||
pinctrl-names = "default";
|
||||
cooling-min-state = <0>;
|
||||
cooling-max-state = <3>;
|
||||
#cooling-cells = <2>;
|
||||
pwms = <&pwm 1 255>;
|
||||
cooling-levels = <0 150 200 255>;
|
||||
};
|
||||
};
|
||||
|
||||
&sdhc_2 {
|
||||
pinctrl-0 = <&sd_pins>;
|
||||
pinctrl-names = "default";
|
||||
cd-gpios = <&tlmm 62 1>;
|
||||
sd-ldo-gpios = <&tlmm 66 1>;
|
||||
status = "ok";
|
||||
};
|
||||
@@ -0,0 +1,343 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
|
||||
/dts-v1/;
|
||||
|
||||
#include "qcom-ipq6018.dtsi"
|
||||
#include "qcom-ipq6018-rpm-regulator.dtsi"
|
||||
#include "qcom-ipq6018-cpr-regulator.dtsi"
|
||||
#include "qcom-ipq6018-cp-cpu.dtsi"
|
||||
#include <dt-bindings/input/input.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
/ {
|
||||
model = "YunCore AX840";
|
||||
compatible = "yuncore,ax840", "qcom,ipq6018-cp03", "qcom,ipq6018";
|
||||
|
||||
#address-cells = <0x2>;
|
||||
#size-cells = <0x2>;
|
||||
interrupt-parent = <&intc>;
|
||||
|
||||
aliases {
|
||||
/* Aliases as required by u-boot to patch MAC addresses */
|
||||
ethernet0 = "/soc/dp2";
|
||||
ethernet1 = "/soc/dp1";
|
||||
|
||||
serial0 = &blsp1_uart3;
|
||||
serial1 = &blsp1_uart2;
|
||||
|
||||
led-boot = &led_system;
|
||||
led-failsafe = &led_system;
|
||||
led-running = &led_system;
|
||||
led-upgrade = &led_system;
|
||||
};
|
||||
|
||||
chosen {
|
||||
bootargs = "console=ttyMSM0,115200,n8 rw init=/init";
|
||||
bootargs-append = " swiotlb=1 coherent_pool=2M";
|
||||
};
|
||||
|
||||
reserved-memory {
|
||||
tzapp:tzapp@49B00000 { /* TZAPPS */
|
||||
no-map;
|
||||
reg = <0x0 0x49B00000 0x0 0x00600000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&tlmm {
|
||||
uart_pins: uart_pins {
|
||||
mux {
|
||||
pins = "gpio44", "gpio45";
|
||||
function = "blsp2_uart";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
};
|
||||
|
||||
spi_0_pins: spi_0_pins {
|
||||
mux {
|
||||
pins = "gpio38", "gpio39", "gpio40", "gpio41";
|
||||
function = "blsp0_spi";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
};
|
||||
|
||||
qpic_pins: qpic_pins {
|
||||
data_0 {
|
||||
pins = "gpio15";
|
||||
function = "qpic_pad0";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
|
||||
data_1 {
|
||||
pins = "gpio12";
|
||||
function = "qpic_pad1";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
|
||||
data_2 {
|
||||
pins = "gpio13";
|
||||
function = "qpic_pad2";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
|
||||
data_3 {
|
||||
pins = "gpio14";
|
||||
function = "qpic_pad3";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
|
||||
data_4 {
|
||||
pins = "gpio5";
|
||||
function = "qpic_pad4";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
|
||||
data_5 {
|
||||
pins = "gpio6";
|
||||
function = "qpic_pad5";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
|
||||
data_6 {
|
||||
pins = "gpio7";
|
||||
function = "qpic_pad6";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
|
||||
data_7 {
|
||||
pins = "gpio8";
|
||||
function = "qpic_pad7";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
|
||||
qpic_pad {
|
||||
pins = "gpio1", "gpio3", "gpio4",
|
||||
"gpio10", "gpio11", "gpio17";
|
||||
function = "qpic_pad";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
};
|
||||
|
||||
button_pins: button_pins {
|
||||
rst_button {
|
||||
pins = "gpio19";
|
||||
function = "gpio";
|
||||
drive-strength = <8>;
|
||||
bias-pull-up;
|
||||
};
|
||||
};
|
||||
|
||||
mdio_pins: mdio_pinmux {
|
||||
mux_0 {
|
||||
pins = "gpio64";
|
||||
function = "mdc";
|
||||
drive-strength = <8>;
|
||||
bias-pull-up;
|
||||
};
|
||||
|
||||
mux_1 {
|
||||
pins = "gpio65";
|
||||
function = "mdio";
|
||||
drive-strength = <8>;
|
||||
bias-pull-up;
|
||||
};
|
||||
|
||||
mux_2 {
|
||||
pins = "gpio75";
|
||||
function = "gpio";
|
||||
bias-pull-up;
|
||||
};
|
||||
};
|
||||
|
||||
leds_pins: leds_pins {
|
||||
led_blue {
|
||||
pins = "gpio35";
|
||||
function = "gpio";
|
||||
drive-strength = <2>;
|
||||
bias-pull-down;
|
||||
};
|
||||
|
||||
led_green {
|
||||
pins = "gpio37";
|
||||
function = "gpio";
|
||||
drive-strength = <2>;
|
||||
bias-pull-down;
|
||||
};
|
||||
|
||||
led_red {
|
||||
pins = "gpio32";
|
||||
function = "gpio";
|
||||
drive-strength = <2>;
|
||||
bias-pull-down;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&soc {
|
||||
mdio: mdio@90000 {
|
||||
status = "ok";
|
||||
|
||||
pinctrl-0 = <&mdio_pins>;
|
||||
pinctrl-names = "default";
|
||||
phy-reset-gpio = <&tlmm 75 0>;
|
||||
|
||||
ethernet-phy@0 {
|
||||
reg = <0x03>;
|
||||
};
|
||||
|
||||
ethernet-phy@1 {
|
||||
reg = <0x04>;
|
||||
};
|
||||
};
|
||||
|
||||
ess-switch@3a000000 {
|
||||
switch_cpu_bmp = <0x01>; /* cpu port bitmap */
|
||||
switch_lan_bmp = <0x10>; /* lan port bitmap */
|
||||
switch_wan_bmp = <0x20>; /* wan port bitmap */
|
||||
switch_inner_bmp = <0x80>; /*inner port bitmap*/
|
||||
switch_mac_mode = <0x00>; /* mac mode for uniphy instance0*/
|
||||
switch_mac_mode1 = <0xff>; /* mac mode for uniphy instance1*/
|
||||
switch_mac_mode2 = <0xff>; /* mac mode for uniphy instance2*/
|
||||
|
||||
qcom,port_phyinfo {
|
||||
port@3 {
|
||||
port_id = <0x04>;
|
||||
phy_address = <0x03>;
|
||||
};
|
||||
|
||||
port@4 {
|
||||
port_id = <0x05>;
|
||||
phy_address = <0x04>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
dp1 {
|
||||
device_type = "network";
|
||||
compatible = "qcom,nss-dp";
|
||||
qcom,id = <0x05>;
|
||||
reg = <0x3a001800 0x200>;
|
||||
qcom,mactype = <0x00>;
|
||||
local-mac-address = [00 00 00 00 00 00];
|
||||
qcom,link-poll = <0x01>;
|
||||
qcom,phy-mdio-addr = <0x04>;
|
||||
phy-mode = "sgmii";
|
||||
};
|
||||
|
||||
dp2 {
|
||||
device_type = "network";
|
||||
compatible = "qcom,nss-dp";
|
||||
qcom,id = <0x04>;
|
||||
reg = <0x3a001600 0x200>;
|
||||
qcom,mactype = <0x00>;
|
||||
local-mac-address = [00 00 00 00 00 00];
|
||||
qcom,link-poll = <0x01>;
|
||||
qcom,phy-mdio-addr = <0x03>;
|
||||
phy-mode = "sgmii";
|
||||
};
|
||||
|
||||
gpio_keys {
|
||||
compatible = "gpio-keys";
|
||||
|
||||
pinctrl-0 = <&button_pins>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
reset {
|
||||
label = "reset";
|
||||
linux,code = <KEY_RESTART>;
|
||||
gpios = <&tlmm 19 GPIO_ACTIVE_LOW>;
|
||||
linux,input-type = <1>;
|
||||
debounce-interval = <60>;
|
||||
};
|
||||
};
|
||||
|
||||
leds {
|
||||
compatible = "gpio-leds";
|
||||
|
||||
pinctrl-0 = <&leds_pins>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
led_system: system {
|
||||
label = "ax860:green:system";
|
||||
gpio = <&tlmm 37 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
|
||||
wlan2g {
|
||||
label = "ax860:blue:wlan2g";
|
||||
gpio = <&tlmm 35 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
|
||||
wlan5g {
|
||||
label = "ax860:red:wlan5g";
|
||||
gpio = <&tlmm 32 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&blsp1_uart3 {
|
||||
pinctrl-0 = <&uart_pins>;
|
||||
pinctrl-names = "default";
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&spi_0 {
|
||||
pinctrl-0 = <&spi_0_pins>;
|
||||
pinctrl-names = "default";
|
||||
cs-select = <0>;
|
||||
status = "ok";
|
||||
|
||||
m25p80@0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
reg = <0>;
|
||||
compatible = "n25q128a11";
|
||||
linux,modalias = "m25p80", "n25q128a11";
|
||||
spi-max-frequency = <50000000>;
|
||||
use-default-sizes;
|
||||
};
|
||||
};
|
||||
|
||||
&qpic_bam {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&nand {
|
||||
pinctrl-0 = <&qpic_pins>;
|
||||
pinctrl-names = "default";
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&nss_crypto {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&cpu0_opp_table {
|
||||
compatible = "operating-points-v2";
|
||||
opp-shared;
|
||||
|
||||
opp03 {
|
||||
opp-hz = /bits/ 64 <1200000000>;
|
||||
opp-microvolt = <3>;
|
||||
clock-latency-ns = <200000>;
|
||||
};
|
||||
|
||||
/delete-node/ opp04;
|
||||
/delete-node/ opp05;
|
||||
/delete-node/ opp06;
|
||||
};
|
||||
|
||||
&qseecom {
|
||||
mem-start = <0x49B00000>;
|
||||
mem-size = <0x600000>;
|
||||
status = "ok";
|
||||
};
|
||||
@@ -39,6 +39,11 @@
|
||||
ethernet3 = "/soc/dp4";
|
||||
ethernet4 = "/soc/dp5";
|
||||
ethernet5 = "/soc/dp6";
|
||||
|
||||
led-boot = &led_power;
|
||||
led-failsafe = &led_power;
|
||||
led-running = &led_power;
|
||||
led-upgrade = &led_power;
|
||||
};
|
||||
|
||||
chosen {
|
||||
@@ -46,7 +51,7 @@
|
||||
#ifdef __IPQ_MEM_PROFILE_256_MB__
|
||||
bootargs-append = " swiotlb=1";
|
||||
#else
|
||||
bootargs-append = " swiotlb=1 coherent_pool=2M";
|
||||
bootargs-append = " swiotlb=1 coherent_pool=2M vmalloc=600M";
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -325,15 +330,22 @@
|
||||
};
|
||||
|
||||
led_pins: led_pins {
|
||||
led_2g {
|
||||
pins = "gpio42";
|
||||
led_red {
|
||||
pins = "gpio25";
|
||||
function = "gpio";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
|
||||
led_5g {
|
||||
pins = "gpio43";
|
||||
led_green {
|
||||
pins = "gpio26";
|
||||
function = "gpio";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
|
||||
led_blue {
|
||||
pins = "gpio27";
|
||||
function = "gpio";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
@@ -379,7 +391,7 @@
|
||||
pinctrl-0 = <&pwm_pins>;
|
||||
pinctrl-names = "default";
|
||||
used-pwm-indices = <1>, <1>, <1>, <0>;
|
||||
status = "ok";
|
||||
// status = "ok";
|
||||
};
|
||||
gpio_keys {
|
||||
compatible = "gpio-keys";
|
||||
@@ -810,15 +822,21 @@
|
||||
pinctrl-0 = <&led_pins>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
led_2g {
|
||||
label = "led_2g";
|
||||
gpio = <&tlmm 42 GPIO_ACTIVE_HIGH>;
|
||||
led_red {
|
||||
label = "red:status";
|
||||
gpio = <&tlmm 25 GPIO_ACTIVE_HIGH>;
|
||||
default-state = "off";
|
||||
};
|
||||
|
||||
led_5g {
|
||||
label = "led_5g";
|
||||
gpio = <&tlmm 43 GPIO_ACTIVE_HIGH>;
|
||||
led_power: led_green {
|
||||
label = "green:status";
|
||||
gpio = <&tlmm 26 GPIO_ACTIVE_HIGH>;
|
||||
default-state = "on";
|
||||
};
|
||||
|
||||
led_blue {
|
||||
label = "blue:status";
|
||||
gpio = <&tlmm 27 GPIO_ACTIVE_HIGH>;
|
||||
default-state = "off";
|
||||
};
|
||||
};
|
||||
|
||||
@@ -9,6 +9,26 @@ define Device/cybertan_eww622_a1
|
||||
endef
|
||||
TARGET_DEVICES += cybertan_eww622_a1
|
||||
|
||||
define Device/edgecore_eap104
|
||||
DEVICE_TITLE := EdgeCore EAP104
|
||||
DEVICE_DTS := qcom-ipq5018-eap104
|
||||
SUPPORTED_DEVICES := edgecore,eap104
|
||||
DEVICE_PACKAGES := ath11k-wifi-edgecore-eap104 ath11k-firmware-ipq50xx-spruce ath11k-firmware-qcn6122
|
||||
DEVICE_DTS_CONFIG := config@mp03.5-c1
|
||||
endef
|
||||
TARGET_DEVICES += edgecore_eap104
|
||||
|
||||
define Device/motorola_q14
|
||||
DEVICE_TITLE := Motorola Q14
|
||||
DEVICE_DTS := qcom-ipq5018-q14
|
||||
SUPPORTED_DEVICES := motorola,q14
|
||||
DEVICE_PACKAGES := ath11k-wifi-motorola-q14 ath11k-firmware-ipq50xx-spruce ath11k-firmware-qcn6122
|
||||
DEVICE_DTS_CONFIG := config@mp03.5-c1
|
||||
IMAGES := sysupgrade.tar mmc-factory.bin
|
||||
IMAGE/mmc-factory.bin := append-ubi | qsdk-ipq-factory-mmc
|
||||
endef
|
||||
TARGET_DEVICES += motorola_q14
|
||||
|
||||
define Device/qcom_mp03_1
|
||||
DEVICE_TITLE := Qualcomm Maple 03.1
|
||||
DEVICE_DTS := qcom-ipq5018-mp03.1
|
||||
|
||||
@@ -1,16 +1,5 @@
|
||||
KERNEL_LOADADDR := 0x41008000
|
||||
|
||||
define Device/cig_wf188
|
||||
DEVICE_TITLE := Cigtech WF-188
|
||||
DEVICE_DTS := qcom-ipq6018-cig-wf188
|
||||
DEVICE_DTS_CONFIG := config@cp03-c1
|
||||
SUPPORTED_DEVICES := cig,wf188
|
||||
IMAGES := sysupgrade.tar
|
||||
IMAGE/sysupgrade.tar/squashfs := append-rootfs | pad-rootfs | sysupgrade-tar rootfs=$$$$@ | append-metadata
|
||||
DEVICE_PACKAGES := ath11k-wifi-cig-wf188 uboot-env
|
||||
endef
|
||||
TARGET_DEVICES += cig_wf188
|
||||
|
||||
define Device/cig_wf188n
|
||||
DEVICE_TITLE := Cigtech WF-188n
|
||||
DEVICE_DTS := qcom-ipq6018-cig-wf188n
|
||||
@@ -43,7 +32,7 @@ define Device/edgecore_eap101
|
||||
DEVICE_DTS := qcom-ipq6018-edgecore-eap101
|
||||
DEVICE_DTS_CONFIG := config@cp01-c1
|
||||
SUPPORTED_DEVICES := edgecore,eap101
|
||||
DEVICE_PACKAGES := ath11k-wifi-edgecore-eap101 uboot-envtools
|
||||
DEVICE_PACKAGES := ath11k-wifi-edgecore-eap101 uboot-envtools -kmod-usb-dwc3-of-simple kmod-usb-dwc3-qcom kmod-usb3 kmod-usb2
|
||||
endef
|
||||
TARGET_DEVICES += edgecore_eap101
|
||||
|
||||
@@ -52,7 +41,7 @@ define Device/wallys_dr6018
|
||||
DEVICE_DTS := qcom-ipq6018-wallys-dr6018
|
||||
DEVICE_DTS_CONFIG := config@cp01-c4
|
||||
SUPPORTED_DEVICES := wallys,dr6018
|
||||
DEVICE_PACKAGES := ath11k-wifi-wallys-dr6018 uboot-envtools
|
||||
DEVICE_PACKAGES := ath11k-wifi-wallys-dr6018 uboot-envtools -kmod-usb-dwc3-of-simple kmod-usb-dwc3-qcom kmod-usb3 kmod-usb2
|
||||
endef
|
||||
TARGET_DEVICES += wallys_dr6018
|
||||
|
||||
@@ -72,3 +61,30 @@ define Device/qcom_cp01_c1
|
||||
DEVICE_PACKAGES := ath11k-wifi-qcom-ipq6018
|
||||
endef
|
||||
TARGET_DEVICES += qcom_cp01_c1
|
||||
|
||||
define Device/glinet_ax1800
|
||||
DEVICE_TITLE := GL-iNet AX1800
|
||||
DEVICE_DTS := qcom-ipq6018-gl-ax1800
|
||||
SUPPORTED_DEVICES := glinet,ax1800
|
||||
DEVICE_DTS_CONFIG := config@cp03-c1
|
||||
DEVICE_PACKAGES := ath11k-wifi-gl-ax1800 -kmod-usb-dwc3-of-simple kmod-usb-dwc3-qcom kmod-usb3
|
||||
endef
|
||||
TARGET_DEVICES += glinet_ax1800
|
||||
|
||||
define Device/glinet_axt1800
|
||||
DEVICE_TITLE := GL-iNet AXT1800
|
||||
DEVICE_DTS := qcom-ipq6018-gl-axt1800
|
||||
SUPPORTED_DEVICES := glinet,axt1800
|
||||
DEVICE_DTS_CONFIG := config@cp03-c1
|
||||
DEVICE_PACKAGES := ath11k-wifi-gl-axt1800 -kmod-usb-dwc3-of-simple kmod-usb-dwc3-qcom kmod-usb3
|
||||
endef
|
||||
TARGET_DEVICES += glinet_axt1800
|
||||
|
||||
define Device/yuncore_ax840
|
||||
DEVICE_TITLE := YunCore AX840
|
||||
DEVICE_DTS := qcom-ipq6018-yuncore-ax840
|
||||
DEVICE_DTS_CONFIG := config@cp03-c1
|
||||
SUPPORTED_DEVICES := yuncore,ax840
|
||||
DEVICE_PACKAGES := ath11k-wifi-yuncore-ax840 uboot-env
|
||||
endef
|
||||
TARGET_DEVICES += yuncore_ax840
|
||||
|
||||
@@ -41,6 +41,8 @@ define Device/cig_wf196
|
||||
DEVICE_DTS := qcom-ipq807x-wf196
|
||||
DEVICE_DTS_CONFIG=config@hk14
|
||||
SUPPORTED_DEVICES := cig,wf196
|
||||
BLOCKSIZE := 256k
|
||||
PAGESIZE := 4096
|
||||
DEVICE_PACKAGES := ath11k-wifi-cig-wf196 aq-fw-download uboot-envtools kmod-usb3 kmod-usb2 \
|
||||
ath11k-firmware-qcn9000 ath11k-wifi-cig-wf196_6g
|
||||
endef
|
||||
|
||||
@@ -3,7 +3,7 @@ SUBTARGET:=ipq50xx
|
||||
BOARDNAME:=IPQ50XX
|
||||
CPU_TYPE:=cortex-a7
|
||||
|
||||
DEFAULT_PACKAGES += ath11k-firmware-ipq50xx qca-nss-fw-ipq50xx
|
||||
DEFAULT_PACKAGES += qca-nss-fw-ipq50xx
|
||||
|
||||
define Target/Description
|
||||
Build firmware image for IPQ50xx SoC devices.
|
||||
|
||||
@@ -111,3 +111,22 @@ define KernelPackage/diag-char/description
|
||||
endef
|
||||
|
||||
$(eval $(call KernelPackage,diag-char))
|
||||
|
||||
define KernelPackage/usb-dwc3-qcom
|
||||
TITLE:=DWC3 Qualcomm USB driver
|
||||
DEPENDS:=@(!LINUX_4_14) @TARGET_ipq807x +kmod-usb-dwc3
|
||||
KCONFIG:= CONFIG_USB_DWC3_QCOM
|
||||
FILES:= $(LINUX_DIR)/drivers/usb/dwc3/dwc3-qcom.ko \
|
||||
$(LINUX_DIR)/drivers/usb/dwc3/dbm.ko
|
||||
AUTOLOAD:=$(call AutoLoad,53,dwc3-qcom dbm,1)
|
||||
$(call AddDepends/usb)
|
||||
endef
|
||||
|
||||
define KernelPackage/usb-dwc3-qcom/description
|
||||
Some Qualcomm SoCs use DesignWare Core IP for USB2/3 functionality.
|
||||
This driver also handles Qscratch wrapper which is needed for
|
||||
peripheral mode support.
|
||||
endef
|
||||
|
||||
|
||||
$(eval $(call KernelPackage,usb-dwc3-qcom))
|
||||
|
||||
25
feeds/ipq807x/ipq807x/patches/001-backport_kbuild_fix.patch
Normal file
25
feeds/ipq807x/ipq807x/patches/001-backport_kbuild_fix.patch
Normal file
@@ -0,0 +1,25 @@
|
||||
--- a/scripts/Makefile.lib
|
||||
+++ b/scripts/Makefile.lib
|
||||
@@ -96,10 +96,10 @@ obj-dirs := $(addprefix $(obj)/,$(obj-di
|
||||
# Note: Files that end up in two or more modules are compiled without the
|
||||
# KBUILD_MODNAME definition. The reason is that any made-up name would
|
||||
# differ in different configs.
|
||||
-name-fix = $(subst $(comma),_,$(subst -,_,$1))
|
||||
-basename_flags = -D"KBUILD_BASENAME=KBUILD_STR($(call name-fix,$(basetarget)))"
|
||||
+name-fix = $(squote)$(quote)$(subst $(comma),_,$(subst -,_,$1))$(quote)$(squote)
|
||||
+basename_flags = -DKBUILD_BASENAME=$(call name-fix,$(basetarget))
|
||||
modname_flags = $(if $(filter 1,$(words $(modname))),\
|
||||
- -D"KBUILD_MODNAME=KBUILD_STR($(call name-fix,$(modname)))")
|
||||
+ -DKBUILD_MODNAME=$(call name-fix,$(modname)))
|
||||
|
||||
orig_c_flags = $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(KBUILD_SUBDIR_CCFLAGS) \
|
||||
$(ccflags-y) $(CFLAGS_$(basetarget).o)
|
||||
@@ -155,7 +155,7 @@ endif
|
||||
|
||||
c_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \
|
||||
$(__c_flags) $(modkern_cflags) \
|
||||
- -D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags)
|
||||
+ $(basename_flags) $(modname_flags)
|
||||
|
||||
a_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \
|
||||
$(__a_flags) $(modkern_aflags)
|
||||
14
feeds/ipq807x/ipq807x/patches/108-add-W25N01GW.patch
Normal file
14
feeds/ipq807x/ipq807x/patches/108-add-W25N01GW.patch
Normal file
@@ -0,0 +1,14 @@
|
||||
Index: linux-4.4.60-qsdk-11f09717303ecd83c3a64e9efe23f25921dc1016/drivers/mtd/nand/qcom_nandc.c
|
||||
===================================================================
|
||||
--- linux-4.4.60-qsdk-11f09717303ecd83c3a64e9efe23f25921dc1016.orig/drivers/mtd/nand/qcom_nandc.c
|
||||
+++ linux-4.4.60-qsdk-11f09717303ecd83c3a64e9efe23f25921dc1016/drivers/mtd/nand/qcom_nandc.c
|
||||
@@ -405,6 +405,9 @@ struct nand_flash_dev qspinand_flash_ids
|
||||
{"MX35UF1GE4AC SPI NAND 1G 1.8V",
|
||||
{ .id = {0xc2, 0x92} },
|
||||
SZ_2K, SZ_128, SZ_128K, 0, 2, 64, NAND_ECC_INFO(4, SZ_512), 0},
|
||||
+ {"W25N01GW SPI NAND 1.8V 1G-BIT",
|
||||
+ { .id = {0xef, 0xba} },
|
||||
+ SZ_2K, SZ_128, SZ_128K, 0, 2, 64, NAND_ECC_INFO(4, SZ_512), 0},
|
||||
{NULL}
|
||||
};
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
From fd65e5a95d08389444e8591a20538b3edece0e15 Mon Sep 17 00:00:00 2001
|
||||
From: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
|
||||
Date: Fri, 31 Jul 2020 19:26:16 +0300
|
||||
Subject: [PATCH] net: bridge: clear bridge's private skb space on xmit
|
||||
|
||||
We need to clear all of the bridge private skb variables as they can be
|
||||
stale due to the packet being recirculated through the stack and then
|
||||
transmitted through the bridge device. Similar memset is already done on
|
||||
bridge's input. We've seen cases where proxyarp_replied was 1 on routed
|
||||
multicast packets transmitted through the bridge to ports with neigh
|
||||
suppress which were getting dropped. Same thing can in theory happen with
|
||||
the port isolation bit as well.
|
||||
|
||||
Fixes: 821f1b21cabb ("bridge: add new BR_NEIGH_SUPPRESS port flag to suppress arp and nd flood")
|
||||
Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
net/bridge/br_device.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
|
||||
index 8c7b78f8bc23..9a2fb4aa1a10 100644
|
||||
--- a/net/bridge/br_device.c
|
||||
+++ b/net/bridge/br_device.c
|
||||
@@ -36,6 +36,8 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
const unsigned char *dest;
|
||||
u16 vid = 0;
|
||||
|
||||
+ memset(skb->cb, 0, sizeof(struct br_input_skb_cb));
|
||||
+
|
||||
rcu_read_lock();
|
||||
nf_ops = rcu_dereference(nf_br_ops);
|
||||
if (nf_ops && nf_ops->br_dev_xmit_hook(skb)) {
|
||||
--
|
||||
2.25.1
|
||||
|
||||
@@ -46,7 +46,50 @@ Cc: Hannes Frederic Sowa <hannes@stressinduktion.org>
|
||||
wake_up_process(thread);
|
||||
return;
|
||||
}
|
||||
@@ -5053,16 +5055,25 @@ static int napi_poll(struct napi_struct
|
||||
@@ -4745,12 +4747,14 @@ void __napi_complete(struct napi_struct
|
||||
list_del_init(&n->poll_list);
|
||||
smp_mb__before_atomic();
|
||||
clear_bit(NAPI_STATE_SCHED, &n->state);
|
||||
+ clear_bit(NAPI_STATE_SCHED_THREADED, &n->state);
|
||||
}
|
||||
EXPORT_SYMBOL(__napi_complete);
|
||||
|
||||
void napi_complete_done(struct napi_struct *n, int work_done)
|
||||
{
|
||||
unsigned long flags;
|
||||
+ unsigned long val, new;
|
||||
|
||||
/*
|
||||
* don't let napi dequeue from the cpu poll list
|
||||
@@ -4771,14 +4775,19 @@ void napi_complete_done(struct napi_stru
|
||||
else
|
||||
napi_gro_flush(n, false);
|
||||
}
|
||||
- if (likely(list_empty(&n->poll_list))) {
|
||||
- WARN_ON_ONCE(!test_and_clear_bit(NAPI_STATE_SCHED, &n->state));
|
||||
- } else {
|
||||
- /* If n->poll_list is not empty, we need to mask irqs */
|
||||
- local_irq_save(flags);
|
||||
- __napi_complete(n);
|
||||
- local_irq_restore(flags);
|
||||
- }
|
||||
+
|
||||
+ /* If n->poll_list is not empty, we need to mask irqs */
|
||||
+ local_irq_save(flags);
|
||||
+ list_del_init(&n->poll_list);
|
||||
+ local_irq_restore(flags);
|
||||
+
|
||||
+ do {
|
||||
+ val = READ_ONCE(n->state);
|
||||
+
|
||||
+ WARN_ON_ONCE(!(val & BIT(NAPI_STATE_SCHED)));
|
||||
+ new = val & ~(BIT(NAPI_STATE_SCHED) |
|
||||
+ BIT(NAPI_STATE_SCHED_THREADED));
|
||||
+ } while (cmpxchg(&n->state, val, new) != val);
|
||||
}
|
||||
EXPORT_SYMBOL(napi_complete_done);
|
||||
|
||||
@@ -5053,16 +5062,25 @@ static int napi_poll(struct napi_struct
|
||||
|
||||
static int napi_thread_wait(struct napi_struct *napi)
|
||||
{
|
||||
|
||||
@@ -34,7 +34,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
|
||||
--- a/net/core/dev.c
|
||||
+++ b/net/core/dev.c
|
||||
@@ -5059,7 +5059,7 @@ static int napi_thread_wait(struct napi_
|
||||
@@ -5066,7 +5066,7 @@ static int napi_thread_wait(struct napi_
|
||||
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
|
||||
@@ -43,7 +43,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
/* Testing SCHED_THREADED bit here to make sure the current
|
||||
* kthread owns this napi and could poll on this napi.
|
||||
* Testing SCHED bit is not enough because SCHED bit might be
|
||||
@@ -5077,6 +5077,7 @@ static int napi_thread_wait(struct napi_
|
||||
@@ -5084,6 +5084,7 @@ static int napi_thread_wait(struct napi_
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
}
|
||||
__set_current_state(TASK_RUNNING);
|
||||
|
||||
@@ -0,0 +1,439 @@
|
||||
From: Daniel Borkmann <daniel@iogearbox.net>
|
||||
Date: Thu, 7 Jan 2016 22:29:47 +0100
|
||||
Subject: [PATCH] net, sched: add clsact qdisc
|
||||
|
||||
This work adds a generalization of the ingress qdisc as a qdisc holding
|
||||
only classifiers. The clsact qdisc works on ingress, but also on egress.
|
||||
In both cases, it's execution happens without taking the qdisc lock, and
|
||||
the main difference for the egress part compared to prior version of [1]
|
||||
is that this can be applied with _any_ underlying real egress qdisc (also
|
||||
classless ones).
|
||||
|
||||
Besides solving the use-case of [1], that is, allowing for more programmability
|
||||
on assigning skb->priority for the mqprio case that is supported by most
|
||||
popular 10G+ NICs, it also opens up a lot more flexibility for other tc
|
||||
applications. The main work on classification can already be done at clsact
|
||||
egress time if the use-case allows and state stored for later retrieval
|
||||
f.e. again in skb->priority with major/minors (which is checked by most
|
||||
classful qdiscs before consulting tc_classify()) and/or in other skb fields
|
||||
like skb->tc_index for some light-weight post-processing to get to the
|
||||
eventual classid in case of a classful qdisc. Another use case is that
|
||||
the clsact egress part allows to have a central egress counterpart to
|
||||
the ingress classifiers, so that classifiers can easily share state (e.g.
|
||||
in cls_bpf via eBPF maps) for ingress and egress.
|
||||
|
||||
Currently, default setups like mq + pfifo_fast would require for this to
|
||||
use, for example, prio qdisc instead (to get a tc_classify() run) and to
|
||||
duplicate the egress classifier for each queue. With clsact, it allows
|
||||
for leaving the setup as is, it can additionally assign skb->priority to
|
||||
put the skb in one of pfifo_fast's bands and it can share state with maps.
|
||||
Moreover, we can access the skb's dst entry (f.e. to retrieve tclassid)
|
||||
w/o the need to perform a skb_dst_force() to hold on to it any longer. In
|
||||
lwt case, we can also use this facility to setup dst metadata via cls_bpf
|
||||
(bpf_skb_set_tunnel_key()) without needing a real egress qdisc just for
|
||||
that (case of IFF_NO_QUEUE devices, for example).
|
||||
|
||||
The realization can be done without any changes to the scheduler core
|
||||
framework. All it takes is that we have two a-priori defined minors/child
|
||||
classes, where we can mux between ingress and egress classifier list
|
||||
(dev->ingress_cl_list and dev->egress_cl_list, latter stored close to
|
||||
dev->_tx to avoid extra cacheline miss for moderate loads). The egress
|
||||
part is a bit similar modelled to handle_ing() and patched to a noop in
|
||||
case the functionality is not used. Both handlers are now called
|
||||
sch_handle_ingress() and sch_handle_egress(), code sharing among the two
|
||||
doesn't seem practical as there are various minor differences in both
|
||||
paths, so that making them conditional in a single handler would rather
|
||||
slow things down.
|
||||
|
||||
Full compatibility to ingress qdisc is provided as well. Since both
|
||||
piggyback on TC_H_CLSACT, only one of them (ingress/clsact) can exist
|
||||
per netdevice, and thus ingress qdisc specific behaviour can be retained
|
||||
for user space. This means, either a user does 'tc qdisc add dev foo ingress'
|
||||
and configures ingress qdisc as usual, or the 'tc qdisc add dev foo clsact'
|
||||
alternative, where both, ingress and egress classifier can be configured
|
||||
as in the below example. ingress qdisc supports attaching classifier to any
|
||||
minor number whereas clsact has two fixed minors for muxing between the
|
||||
lists, therefore to not break user space setups, they are better done as
|
||||
two separate qdiscs.
|
||||
|
||||
I decided to extend the sch_ingress module with clsact functionality so
|
||||
that commonly used code can be reused, the module is being aliased with
|
||||
sch_clsact so that it can be auto-loaded properly. Alternative would have been
|
||||
to add a flag when initializing ingress to alter its behaviour plus aliasing
|
||||
to a different name (as it's more than just ingress). However, the first would
|
||||
end up, based on the flag, choosing the new/old behaviour by calling different
|
||||
function implementations to handle each anyway, the latter would require to
|
||||
register ingress qdisc once again under different alias. So, this really begs
|
||||
to provide a minimal, cleaner approach to have Qdisc_ops and Qdisc_class_ops
|
||||
by its own that share callbacks used by both.
|
||||
|
||||
Example, adding qdisc:
|
||||
|
||||
# tc qdisc add dev foo clsact
|
||||
# tc qdisc show dev foo
|
||||
qdisc mq 0: root
|
||||
qdisc pfifo_fast 0: parent :1 bands 3 priomap 1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1
|
||||
qdisc pfifo_fast 0: parent :2 bands 3 priomap 1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1
|
||||
qdisc pfifo_fast 0: parent :3 bands 3 priomap 1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1
|
||||
qdisc pfifo_fast 0: parent :4 bands 3 priomap 1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1
|
||||
qdisc clsact ffff: parent ffff:fff1
|
||||
|
||||
Adding filters (deleting, etc works analogous by specifying ingress/egress):
|
||||
|
||||
# tc filter add dev foo ingress bpf da obj bar.o sec ingress
|
||||
# tc filter add dev foo egress bpf da obj bar.o sec egress
|
||||
# tc filter show dev foo ingress
|
||||
filter protocol all pref 49152 bpf
|
||||
filter protocol all pref 49152 bpf handle 0x1 bar.o:[ingress] direct-action
|
||||
# tc filter show dev foo egress
|
||||
filter protocol all pref 49152 bpf
|
||||
filter protocol all pref 49152 bpf handle 0x1 bar.o:[egress] direct-action
|
||||
|
||||
A 'tc filter show dev foo' or 'tc filter show dev foo parent ffff:' will
|
||||
show an empty list for clsact. Either using the parent names (ingress/egress)
|
||||
or specifying the full major/minor will then show the related filter lists.
|
||||
|
||||
Prior work on a mqprio prequeue() facility [1] was done mainly by John Fastabend.
|
||||
|
||||
[1] http://patchwork.ozlabs.org/patch/512949/
|
||||
|
||||
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
|
||||
Acked-by: John Fastabend <john.r.fastabend@intel.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
|
||||
--- a/include/linux/netdevice.h
|
||||
+++ b/include/linux/netdevice.h
|
||||
@@ -1770,7 +1770,9 @@ struct net_device {
|
||||
#ifdef CONFIG_XPS
|
||||
struct xps_dev_maps __rcu *xps_maps;
|
||||
#endif
|
||||
-
|
||||
+#ifdef CONFIG_NET_CLS_ACT
|
||||
+ struct tcf_proto __rcu *egress_cl_list;
|
||||
+#endif
|
||||
#ifdef CONFIG_NET_SWITCHDEV
|
||||
u32 offload_fwd_mark;
|
||||
#endif
|
||||
--- a/include/linux/rtnetlink.h
|
||||
+++ b/include/linux/rtnetlink.h
|
||||
@@ -84,6 +84,11 @@ void net_inc_ingress_queue(void);
|
||||
void net_dec_ingress_queue(void);
|
||||
#endif
|
||||
|
||||
+#ifdef CONFIG_NET_EGRESS
|
||||
+void net_inc_egress_queue(void);
|
||||
+void net_dec_egress_queue(void);
|
||||
+#endif
|
||||
+
|
||||
extern void rtnetlink_init(void);
|
||||
extern void __rtnl_unlock(void);
|
||||
|
||||
--- a/include/uapi/linux/pkt_sched.h
|
||||
+++ b/include/uapi/linux/pkt_sched.h
|
||||
@@ -72,6 +72,10 @@ struct tc_estimator {
|
||||
#define TC_H_UNSPEC (0U)
|
||||
#define TC_H_ROOT (0xFFFFFFFFU)
|
||||
#define TC_H_INGRESS (0xFFFFFFF1U)
|
||||
+#define TC_H_CLSACT TC_H_INGRESS
|
||||
+
|
||||
+#define TC_H_MIN_INGRESS 0xFFF2U
|
||||
+#define TC_H_MIN_EGRESS 0xFFF3U
|
||||
|
||||
/* Need to corrospond to iproute2 tc/tc_core.h "enum link_layer" */
|
||||
enum tc_link_layer {
|
||||
--- a/net/core/dev.c
|
||||
+++ b/net/core/dev.c
|
||||
@@ -1697,6 +1697,22 @@ void net_dec_ingress_queue(void)
|
||||
EXPORT_SYMBOL_GPL(net_dec_ingress_queue);
|
||||
#endif
|
||||
|
||||
+#ifdef CONFIG_NET_EGRESS
|
||||
+static struct static_key egress_needed __read_mostly;
|
||||
+
|
||||
+void net_inc_egress_queue(void)
|
||||
+{
|
||||
+ static_key_slow_inc(&egress_needed);
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(net_inc_egress_queue);
|
||||
+
|
||||
+void net_dec_egress_queue(void)
|
||||
+{
|
||||
+ static_key_slow_dec(&egress_needed);
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(net_dec_egress_queue);
|
||||
+#endif
|
||||
+
|
||||
static struct static_key netstamp_needed __read_mostly;
|
||||
#ifdef HAVE_JUMP_LABEL
|
||||
static atomic_t netstamp_needed_deferred;
|
||||
@@ -2936,7 +2952,6 @@ static inline int __dev_xmit_skb(struct
|
||||
bool contended;
|
||||
int rc;
|
||||
|
||||
- qdisc_pkt_len_init(skb);
|
||||
qdisc_calculate_pkt_len(skb, q);
|
||||
/*
|
||||
* Heuristic to force contended enqueues to serialize on a
|
||||
@@ -3028,6 +3043,49 @@ int dev_loopback_xmit(struct net *net, s
|
||||
}
|
||||
EXPORT_SYMBOL(dev_loopback_xmit);
|
||||
|
||||
+#ifdef CONFIG_NET_EGRESS
|
||||
+static struct sk_buff *
|
||||
+sch_handle_egress(struct sk_buff *skb, int *ret, struct net_device *dev)
|
||||
+{
|
||||
+ struct tcf_proto *cl = rcu_dereference_bh(dev->egress_cl_list);
|
||||
+ struct tcf_result cl_res;
|
||||
+
|
||||
+ if (!cl)
|
||||
+ return skb;
|
||||
+
|
||||
+ /* skb->tc_verd and qdisc_skb_cb(skb)->pkt_len were already set
|
||||
+ * earlier by the caller.
|
||||
+ */
|
||||
+ qdisc_bstats_cpu_update(cl->q, skb);
|
||||
+
|
||||
+ switch (tc_classify(skb, cl, &cl_res, false)) {
|
||||
+ case TC_ACT_OK:
|
||||
+ case TC_ACT_RECLASSIFY:
|
||||
+ skb->tc_index = TC_H_MIN(cl_res.classid);
|
||||
+ break;
|
||||
+ case TC_ACT_SHOT:
|
||||
+ qdisc_qstats_cpu_drop(cl->q);
|
||||
+ *ret = NET_XMIT_DROP;
|
||||
+ goto drop;
|
||||
+ case TC_ACT_STOLEN:
|
||||
+ case TC_ACT_QUEUED:
|
||||
+ *ret = NET_XMIT_SUCCESS;
|
||||
+drop:
|
||||
+ kfree_skb(skb);
|
||||
+ return NULL;
|
||||
+ case TC_ACT_REDIRECT:
|
||||
+ /* No need to push/pop skb's mac_header here on egress! */
|
||||
+ skb_do_redirect(skb);
|
||||
+ *ret = NET_XMIT_SUCCESS;
|
||||
+ return NULL;
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ return skb;
|
||||
+}
|
||||
+#endif /* CONFIG_NET_EGRESS */
|
||||
+
|
||||
static inline int get_xps_queue(struct net_device *dev, struct sk_buff *skb)
|
||||
{
|
||||
#ifdef CONFIG_XPS
|
||||
@@ -3152,6 +3210,17 @@ static int __dev_queue_xmit(struct sk_bu
|
||||
|
||||
skb_update_prio(skb);
|
||||
|
||||
+ qdisc_pkt_len_init(skb);
|
||||
+#ifdef CONFIG_NET_CLS_ACT
|
||||
+ skb->tc_verd = SET_TC_AT(skb->tc_verd, AT_EGRESS);
|
||||
+# ifdef CONFIG_NET_EGRESS
|
||||
+ if (static_key_false(&egress_needed)) {
|
||||
+ skb = sch_handle_egress(skb, &rc, dev);
|
||||
+ if (!skb)
|
||||
+ goto out;
|
||||
+ }
|
||||
+# endif
|
||||
+#endif
|
||||
/* If device/qdisc don't need skb->dst, release it right now while
|
||||
* its hot in this cpu cache.
|
||||
*/
|
||||
@@ -3173,9 +3242,6 @@ static int __dev_queue_xmit(struct sk_bu
|
||||
txq = netdev_pick_tx(dev, skb, accel_priv);
|
||||
q = rcu_dereference_bh(txq->qdisc);
|
||||
|
||||
-#ifdef CONFIG_NET_CLS_ACT
|
||||
- skb->tc_verd = SET_TC_AT(skb->tc_verd, AT_EGRESS);
|
||||
-#endif
|
||||
trace_net_dev_queue(skb);
|
||||
if (q->enqueue) {
|
||||
rc = __dev_xmit_skb(skb, q, dev, txq);
|
||||
@@ -3750,9 +3816,9 @@ int (*br_fdb_test_addr_hook)(struct net_
|
||||
EXPORT_SYMBOL_GPL(br_fdb_test_addr_hook);
|
||||
#endif
|
||||
|
||||
-static inline struct sk_buff *handle_ing(struct sk_buff *skb,
|
||||
- struct packet_type **pt_prev,
|
||||
- int *ret, struct net_device *orig_dev)
|
||||
+static inline struct sk_buff *
|
||||
+sch_handle_ingress(struct sk_buff *skb, struct packet_type **pt_prev, int *ret,
|
||||
+ struct net_device *orig_dev)
|
||||
{
|
||||
#ifdef CONFIG_NET_CLS_ACT
|
||||
struct tcf_proto *cl = rcu_dereference_bh(skb->dev->ingress_cl_list);
|
||||
@@ -3974,7 +4040,7 @@ another_round:
|
||||
skip_taps:
|
||||
#ifdef CONFIG_NET_INGRESS
|
||||
if (static_key_false(&ingress_needed)) {
|
||||
- skb = handle_ing(skb, &pt_prev, &ret, orig_dev);
|
||||
+ skb = sch_handle_ingress(skb, &pt_prev, &ret, orig_dev);
|
||||
if (!skb)
|
||||
goto out;
|
||||
|
||||
--- a/net/Kconfig
|
||||
+++ b/net/Kconfig
|
||||
@@ -54,6 +54,9 @@ config COMPAT_NETLINK_MESSAGES
|
||||
config NET_INGRESS
|
||||
bool
|
||||
|
||||
+config NET_EGRESS
|
||||
+ bool
|
||||
+
|
||||
menu "Networking options"
|
||||
|
||||
source "net/packet/Kconfig"
|
||||
--- a/net/sched/cls_bpf.c
|
||||
+++ b/net/sched/cls_bpf.c
|
||||
@@ -291,7 +291,7 @@ static int cls_bpf_prog_from_efd(struct
|
||||
prog->bpf_name = name;
|
||||
prog->filter = fp;
|
||||
|
||||
- if (fp->dst_needed)
|
||||
+ if (fp->dst_needed && !(tp->q->flags & TCQ_F_INGRESS))
|
||||
netif_keep_dst(qdisc_dev(tp->q));
|
||||
|
||||
return 0;
|
||||
--- a/net/sched/Kconfig
|
||||
+++ b/net/sched/Kconfig
|
||||
@@ -342,15 +342,21 @@ config NET_SCH_PIE
|
||||
If unsure, say N.
|
||||
|
||||
config NET_SCH_INGRESS
|
||||
- tristate "Ingress Qdisc"
|
||||
+ tristate "Ingress/classifier-action Qdisc"
|
||||
depends on NET_CLS_ACT
|
||||
select NET_INGRESS
|
||||
+ select NET_EGRESS
|
||||
---help---
|
||||
- Say Y here if you want to use classifiers for incoming packets.
|
||||
+ Say Y here if you want to use classifiers for incoming and/or outgoing
|
||||
+ packets. This qdisc doesn't do anything else besides running classifiers,
|
||||
+ which can also have actions attached to them. In case of outgoing packets,
|
||||
+ classifiers that this qdisc holds are executed in the transmit path
|
||||
+ before real enqueuing to an egress qdisc happens.
|
||||
+
|
||||
If unsure, say Y.
|
||||
|
||||
- To compile this code as a module, choose M here: the
|
||||
- module will be called sch_ingress.
|
||||
+ To compile this code as a module, choose M here: the module will be
|
||||
+ called sch_ingress with alias of sch_clsact.
|
||||
|
||||
config NET_SCH_PLUG
|
||||
tristate "Plug network traffic until release (PLUG)"
|
||||
--- a/net/sched/sch_ingress.c
|
||||
+++ b/net/sched/sch_ingress.c
|
||||
@@ -1,4 +1,5 @@
|
||||
-/* net/sched/sch_ingress.c - Ingress qdisc
|
||||
+/* net/sched/sch_ingress.c - Ingress and clsact qdisc
|
||||
+ *
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
@@ -98,17 +99,100 @@ static struct Qdisc_ops ingress_qdisc_op
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
+static unsigned long clsact_get(struct Qdisc *sch, u32 classid)
|
||||
+{
|
||||
+ switch (TC_H_MIN(classid)) {
|
||||
+ case TC_H_MIN(TC_H_MIN_INGRESS):
|
||||
+ case TC_H_MIN(TC_H_MIN_EGRESS):
|
||||
+ return TC_H_MIN(classid);
|
||||
+ default:
|
||||
+ return 0;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static unsigned long clsact_bind_filter(struct Qdisc *sch,
|
||||
+ unsigned long parent, u32 classid)
|
||||
+{
|
||||
+ return clsact_get(sch, classid);
|
||||
+}
|
||||
+
|
||||
+static struct tcf_proto __rcu **clsact_find_tcf(struct Qdisc *sch,
|
||||
+ unsigned long cl)
|
||||
+{
|
||||
+ struct net_device *dev = qdisc_dev(sch);
|
||||
+
|
||||
+ switch (cl) {
|
||||
+ case TC_H_MIN(TC_H_MIN_INGRESS):
|
||||
+ return &dev->ingress_cl_list;
|
||||
+ case TC_H_MIN(TC_H_MIN_EGRESS):
|
||||
+ return &dev->egress_cl_list;
|
||||
+ default:
|
||||
+ return NULL;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int clsact_init(struct Qdisc *sch, struct nlattr *opt)
|
||||
+{
|
||||
+ net_inc_ingress_queue();
|
||||
+ net_inc_egress_queue();
|
||||
+
|
||||
+ sch->flags |= TCQ_F_CPUSTATS;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void clsact_destroy(struct Qdisc *sch)
|
||||
+{
|
||||
+ struct net_device *dev = qdisc_dev(sch);
|
||||
+
|
||||
+ tcf_destroy_chain(&dev->ingress_cl_list);
|
||||
+ tcf_destroy_chain(&dev->egress_cl_list);
|
||||
+
|
||||
+ net_dec_ingress_queue();
|
||||
+ net_dec_egress_queue();
|
||||
+}
|
||||
+
|
||||
+static const struct Qdisc_class_ops clsact_class_ops = {
|
||||
+ .leaf = ingress_leaf,
|
||||
+ .get = clsact_get,
|
||||
+ .put = ingress_put,
|
||||
+ .walk = ingress_walk,
|
||||
+ .tcf_chain = clsact_find_tcf,
|
||||
+ .bind_tcf = clsact_bind_filter,
|
||||
+ .unbind_tcf = ingress_put,
|
||||
+};
|
||||
+
|
||||
+static struct Qdisc_ops clsact_qdisc_ops __read_mostly = {
|
||||
+ .cl_ops = &clsact_class_ops,
|
||||
+ .id = "clsact",
|
||||
+ .init = clsact_init,
|
||||
+ .destroy = clsact_destroy,
|
||||
+ .dump = ingress_dump,
|
||||
+ .owner = THIS_MODULE,
|
||||
+};
|
||||
+
|
||||
static int __init ingress_module_init(void)
|
||||
{
|
||||
- return register_qdisc(&ingress_qdisc_ops);
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = register_qdisc(&ingress_qdisc_ops);
|
||||
+ if (!ret) {
|
||||
+ ret = register_qdisc(&clsact_qdisc_ops);
|
||||
+ if (ret)
|
||||
+ unregister_qdisc(&ingress_qdisc_ops);
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
static void __exit ingress_module_exit(void)
|
||||
{
|
||||
unregister_qdisc(&ingress_qdisc_ops);
|
||||
+ unregister_qdisc(&clsact_qdisc_ops);
|
||||
}
|
||||
|
||||
module_init(ingress_module_init);
|
||||
module_exit(ingress_module_exit);
|
||||
|
||||
+MODULE_ALIAS("sch_clsact");
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -0,0 +1,75 @@
|
||||
From: Shmulik Ladkani <shmulik.ladkani@gmail.com>
|
||||
Date: Thu, 13 Oct 2016 09:06:41 +0300
|
||||
Subject: [PATCH] net/sched: act_mirred: Rename tcfm_ok_push to
|
||||
tcfm_mac_header_xmit and make it a bool
|
||||
|
||||
'tcfm_ok_push' specifies whether a mac_len sized push is needed upon
|
||||
egress to the target device (if action is performed at ingress).
|
||||
|
||||
Rename it to 'tcfm_mac_header_xmit' as this is actually an attribute of
|
||||
the target device (and use a bool instead of int).
|
||||
|
||||
This allows to decouple the attribute from the action to be taken.
|
||||
|
||||
Signed-off-by: Shmulik Ladkani <shmulik.ladkani@gmail.com>
|
||||
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
|
||||
--- a/include/net/tc_act/tc_mirred.h
|
||||
+++ b/include/net/tc_act/tc_mirred.h
|
||||
@@ -7,7 +7,7 @@ struct tcf_mirred {
|
||||
struct tcf_common common;
|
||||
int tcfm_eaction;
|
||||
int tcfm_ifindex;
|
||||
- int tcfm_ok_push;
|
||||
+ bool tcfm_mac_header_xmit;
|
||||
struct net_device __rcu *tcfm_dev;
|
||||
struct list_head tcfm_list;
|
||||
};
|
||||
--- a/net/sched/act_mirred.c
|
||||
+++ b/net/sched/act_mirred.c
|
||||
@@ -55,10 +55,11 @@ static int tcf_mirred_init(struct net *n
|
||||
int bind)
|
||||
{
|
||||
struct nlattr *tb[TCA_MIRRED_MAX + 1];
|
||||
+ bool mac_header_xmit = false;
|
||||
struct tc_mirred *parm;
|
||||
struct tcf_mirred *m;
|
||||
struct net_device *dev;
|
||||
- int ret, ok_push = 0;
|
||||
+ int ret;
|
||||
|
||||
if (nla == NULL)
|
||||
return -EINVAL;
|
||||
@@ -86,10 +87,10 @@ static int tcf_mirred_init(struct net *n
|
||||
case ARPHRD_IPGRE:
|
||||
case ARPHRD_VOID:
|
||||
case ARPHRD_NONE:
|
||||
- ok_push = 0;
|
||||
+ mac_header_xmit = false;
|
||||
break;
|
||||
default:
|
||||
- ok_push = 1;
|
||||
+ mac_header_xmit = true;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
@@ -123,7 +124,7 @@ static int tcf_mirred_init(struct net *n
|
||||
dev_put(rcu_dereference_protected(m->tcfm_dev, 1));
|
||||
dev_hold(dev);
|
||||
rcu_assign_pointer(m->tcfm_dev, dev);
|
||||
- m->tcfm_ok_push = ok_push;
|
||||
+ m->tcfm_mac_header_xmit = mac_header_xmit;
|
||||
}
|
||||
|
||||
if (ret == ACT_P_CREATED) {
|
||||
@@ -169,7 +170,7 @@ static int tcf_mirred(struct sk_buff *sk
|
||||
goto out;
|
||||
|
||||
if (!(at & AT_EGRESS)) {
|
||||
- if (m->tcfm_ok_push)
|
||||
+ if (m->tcfm_mac_header_xmit)
|
||||
skb_push_rcsum(skb2, skb->mac_len);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
From: Shmulik Ladkani <shmulik.ladkani@gmail.com>
|
||||
Date: Thu, 13 Oct 2016 09:06:42 +0300
|
||||
Subject: [PATCH] net/sched: act_mirred: Refactor detection whether dev needs
|
||||
xmit at mac header
|
||||
|
||||
Move detection logic that tests whether device expects skb data to point
|
||||
at mac_header upon xmit into a function.
|
||||
|
||||
Signed-off-by: Shmulik Ladkani <shmulik.ladkani@gmail.com>
|
||||
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
|
||||
--- a/net/sched/act_mirred.c
|
||||
+++ b/net/sched/act_mirred.c
|
||||
@@ -80,19 +80,7 @@ static int tcf_mirred_init(struct net *n
|
||||
dev = __dev_get_by_index(net, parm->ifindex);
|
||||
if (dev == NULL)
|
||||
return -ENODEV;
|
||||
- switch (dev->type) {
|
||||
- case ARPHRD_TUNNEL:
|
||||
- case ARPHRD_TUNNEL6:
|
||||
- case ARPHRD_SIT:
|
||||
- case ARPHRD_IPGRE:
|
||||
- case ARPHRD_VOID:
|
||||
- case ARPHRD_NONE:
|
||||
- mac_header_xmit = false;
|
||||
- break;
|
||||
- default:
|
||||
- mac_header_xmit = true;
|
||||
- break;
|
||||
- }
|
||||
+ mac_header_xmit = dev_is_mac_header_xmit(dev);
|
||||
} else {
|
||||
dev = NULL;
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
From: Shmulik Ladkani <shmulik.ladkani@gmail.com>
|
||||
Date: Thu, 13 Oct 2016 09:06:44 +0300
|
||||
Subject: [PATCH] net/sched: act_mirred: Implement ingress actions
|
||||
|
||||
Up until now, 'action mirred' supported only egress actions (either
|
||||
TCA_EGRESS_REDIR or TCA_EGRESS_MIRROR).
|
||||
|
||||
This patch implements the corresponding ingress actions
|
||||
TCA_INGRESS_REDIR and TCA_INGRESS_MIRROR.
|
||||
|
||||
This allows attaching filters whose target is to hand matching skbs into
|
||||
the rx processing of a specified device.
|
||||
|
||||
Signed-off-by: Shmulik Ladkani <shmulik.ladkani@gmail.com>
|
||||
Cc: Jamal Hadi Salim <jhs@mojatatu.com>
|
||||
Cc: Eric Dumazet <eric.dumazet@gmail.com>
|
||||
Cc: Cong Wang <xiyou.wangcong@gmail.com>
|
||||
Tested-by: Jamal Hadi Salim <jhs@mojatatu.com>
|
||||
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
|
||||
--- a/net/sched/act_mirred.c
|
||||
+++ b/net/sched/act_mirred.c
|
||||
@@ -33,6 +33,25 @@
|
||||
static LIST_HEAD(mirred_list);
|
||||
static DEFINE_SPINLOCK(mirred_list_lock);
|
||||
|
||||
+static bool tcf_mirred_is_act_redirect(int action)
|
||||
+{
|
||||
+ return action == TCA_EGRESS_REDIR || action == TCA_INGRESS_REDIR;
|
||||
+}
|
||||
+
|
||||
+static u32 tcf_mirred_act_direction(int action)
|
||||
+{
|
||||
+ switch (action) {
|
||||
+ case TCA_EGRESS_REDIR:
|
||||
+ case TCA_EGRESS_MIRROR:
|
||||
+ return AT_EGRESS;
|
||||
+ case TCA_INGRESS_REDIR:
|
||||
+ case TCA_INGRESS_MIRROR:
|
||||
+ return AT_INGRESS;
|
||||
+ default:
|
||||
+ BUG();
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static void tcf_mirred_release(struct tc_action *a, int bind)
|
||||
{
|
||||
struct tcf_mirred *m = to_mirred(a);
|
||||
@@ -72,6 +91,8 @@ static int tcf_mirred_init(struct net *n
|
||||
switch (parm->eaction) {
|
||||
case TCA_EGRESS_MIRROR:
|
||||
case TCA_EGRESS_REDIR:
|
||||
+ case TCA_INGRESS_REDIR:
|
||||
+ case TCA_INGRESS_MIRROR:
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
@@ -129,9 +150,12 @@ static int tcf_mirred(struct sk_buff *sk
|
||||
struct tcf_result *res)
|
||||
{
|
||||
struct tcf_mirred *m = a->priv;
|
||||
+ bool m_mac_header_xmit;
|
||||
struct net_device *dev;
|
||||
struct sk_buff *skb2;
|
||||
- int retval, err;
|
||||
+ int retval, err = 0;
|
||||
+ int m_eaction;
|
||||
+ int mac_len;
|
||||
u32 at;
|
||||
|
||||
tcf_lastuse_update(&m->tcf_tm);
|
||||
@@ -139,6 +163,8 @@ static int tcf_mirred(struct sk_buff *sk
|
||||
bstats_cpu_update(this_cpu_ptr(m->common.cpu_bstats), skb);
|
||||
|
||||
rcu_read_lock();
|
||||
+ m_mac_header_xmit = READ_ONCE(m->tcfm_mac_header_xmit);
|
||||
+ m_eaction = READ_ONCE(m->tcfm_eaction);
|
||||
retval = READ_ONCE(m->tcf_action);
|
||||
dev = rcu_dereference(m->tcfm_dev);
|
||||
if (unlikely(!dev)) {
|
||||
@@ -157,24 +183,37 @@ static int tcf_mirred(struct sk_buff *sk
|
||||
if (!skb2)
|
||||
goto out;
|
||||
|
||||
- if (!(at & AT_EGRESS)) {
|
||||
- if (m->tcfm_mac_header_xmit)
|
||||
+ /* If action's target direction differs than filter's direction,
|
||||
+ * and devices expect a mac header on xmit, then mac push/pull is
|
||||
+ * needed.
|
||||
+ */
|
||||
+ if (at != tcf_mirred_act_direction(m_eaction) && m_mac_header_xmit) {
|
||||
+ if (at & AT_EGRESS) {
|
||||
+ /* caught at egress, act ingress: pull mac */
|
||||
+ mac_len = skb_network_header(skb) - skb_mac_header(skb);
|
||||
+ skb_pull_rcsum(skb2, mac_len);
|
||||
+ } else {
|
||||
+ /* caught at ingress, act egress: push mac */
|
||||
skb_push_rcsum(skb2, skb->mac_len);
|
||||
+ }
|
||||
}
|
||||
|
||||
/* mirror is always swallowed */
|
||||
- if (m->tcfm_eaction != TCA_EGRESS_MIRROR)
|
||||
+ if (tcf_mirred_is_act_redirect(m_eaction))
|
||||
skb2->tc_verd = SET_TC_FROM(skb2->tc_verd, at);
|
||||
|
||||
skb2->skb_iif = skb->dev->ifindex;
|
||||
skb2->dev = dev;
|
||||
skb_sender_cpu_clear(skb2);
|
||||
- err = dev_queue_xmit(skb2);
|
||||
+ if (tcf_mirred_act_direction(m_eaction) & AT_EGRESS)
|
||||
+ err = dev_queue_xmit(skb2);
|
||||
+ else
|
||||
+ err = netif_receive_skb(skb2);
|
||||
|
||||
if (err) {
|
||||
out:
|
||||
qstats_overlimit_inc(this_cpu_ptr(m->common.cpu_qstats));
|
||||
- if (m->tcfm_eaction != TCA_EGRESS_MIRROR)
|
||||
+ if (tcf_mirred_is_act_redirect(m_eaction))
|
||||
retval = TC_ACT_SHOT;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
@@ -13,6 +13,7 @@ PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL:=https://github.com/dtaht/sch_cake.git
|
||||
PKG_MIRROR_HASH:=8bb4fa43368be5b5839a350419701b0bb3881b1641e037affea42630d75e56e6
|
||||
PKG_SOURCE_DATE:=2021-07-09
|
||||
PKG_SOURCE_VERSION:=d9e1398cc9091e9e7c7a740361e4617b75c24427
|
||||
#PKG_MIRROR_HASH:=5bf06a804824db36ae393fc174aeec7b12633176e05a765c0931b39df5bd34df
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2011 OpenWrt.org
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=libprotobuf-c
|
||||
PKG_VERSION:=1.3.1
|
||||
PKG_RELEASE:=2
|
||||
|
||||
PKG_SOURCE:=protobuf-c-$(PKG_VERSION).tar.gz
|
||||
PKG_SOURCE_URL:=https://github.com/protobuf-c/protobuf-c/releases/download/v$(PKG_VERSION)
|
||||
PKG_HASH:=51472d3a191d6d7b425e32b612e477c06f73fe23e07f6a6a839b11808e9d2267
|
||||
PKG_BUILD_DIR:=$(BUILD_DIR)/protobuf-c-$(PKG_VERSION)
|
||||
HOST_BUILD_DIR:=$(BUILD_DIR_HOST)/protobuf-c-$(PKG_VERSION)
|
||||
|
||||
PKG_MAINTAINER:=Rosen Penev <rosenp@gmail.com>
|
||||
PKG_LICENSE:=BSD-2c
|
||||
|
||||
PKG_BUILD_DEPENDS:=protobuf-c/host
|
||||
HOST_BUILD_DEPENDS:=protobuf/host
|
||||
|
||||
PKG_INSTALL:=1
|
||||
PKG_BUILD_PARALLEL:=1
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
include $(INCLUDE_DIR)/host-build.mk
|
||||
|
||||
define Package/libprotobuf-c
|
||||
TITLE:=Protocol Buffers library
|
||||
SECTION:=libs
|
||||
CATEGORY:=Libraries
|
||||
URL:=https://github.com/protobuf-c/protobuf-c
|
||||
endef
|
||||
|
||||
define Package/libprotobuf-c/description
|
||||
Runtime library to use Google Protocol Buffers from C applications.
|
||||
Protocol Buffers are a way of encoding structured data in an efficient yet
|
||||
extensible format. Google uses Protocol Buffers for almost all of its
|
||||
internal RPC protocols and file formats.
|
||||
endef
|
||||
|
||||
CONFIGURE_ARGS += \
|
||||
--enable-shared \
|
||||
--enable-static \
|
||||
--disable-protoc
|
||||
|
||||
define Build/InstallDev
|
||||
$(INSTALL_DIR) $(1)/usr/include/
|
||||
$(CP) $(PKG_INSTALL_DIR)/usr/include/* $(1)/usr/include/
|
||||
$(INSTALL_DIR) $(1)/usr/lib
|
||||
$(CP) $(PKG_INSTALL_DIR)/usr/lib/libprotobuf-c.{a,la,so*} $(1)/usr/lib/
|
||||
$(INSTALL_DIR) $(1)/usr/lib/pkgconfig
|
||||
$(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/* $(1)/usr/lib/pkgconfig/
|
||||
endef
|
||||
|
||||
define Package/libprotobuf-c/install
|
||||
$(INSTALL_DIR) $(1)/usr/lib
|
||||
$(CP) $(PKG_INSTALL_DIR)/usr/lib/libprotobuf-c.so.* $(1)/usr/lib/
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,libprotobuf-c))
|
||||
$(eval $(call HostBuild))
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
Index: protobuf-c-1.3.1/t/generated-code2/cxx-generate-packed-data.cc
|
||||
===================================================================
|
||||
--- protobuf-c-1.3.1.orig/t/generated-code2/cxx-generate-packed-data.cc
|
||||
+++ protobuf-c-1.3.1/t/generated-code2/cxx-generate-packed-data.cc
|
||||
@@ -998,7 +998,7 @@ static void dump_test_packed_repeated_en
|
||||
static void dump_test_unknown_fields (void)
|
||||
{
|
||||
EmptyMess mess;
|
||||
- const google::protobuf::Message::Reflection *reflection = mess.GetReflection();
|
||||
+ const google::protobuf::Reflection *reflection = mess.GetReflection();
|
||||
google::protobuf::UnknownFieldSet *fs = reflection->MutableUnknownFields(&mess);
|
||||
|
||||
#if GOOGLE_PROTOBUF_VERSION >= 2001000
|
||||
@@ -1,110 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2007-2015 OpenWrt.org
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=protobuf
|
||||
PKG_VERSION:=3.7.1
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE:=$(PKG_NAME)-cpp-$(PKG_VERSION).tar.gz
|
||||
PKG_SOURCE_URL:=https://github.com/google/protobuf/releases/download/v$(PKG_VERSION)
|
||||
PKG_HASH:=97f6cdaa0724d5a8cd3375d5f5cf4bd253d5ad5291154f533ed0d94a9d501ef3
|
||||
|
||||
PKG_LICENSE:=BSD-3-Clause
|
||||
PKG_LICENSE_FILES:=LICENSE
|
||||
PKG_CPE_ID:=cpe:/a:google:protobuf
|
||||
|
||||
PKG_BUILD_DEPENDS:=protobuf/host
|
||||
|
||||
PKG_BUILD_PARALLEL:=1
|
||||
PKG_INSTALL:=1
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
include $(INCLUDE_DIR)/host-build.mk
|
||||
|
||||
define Package/protobuf/Default
|
||||
SECTION:=libs
|
||||
CATEGORY:=Libraries
|
||||
TITLE:=A structured data encoding library
|
||||
URL:=https://github.com/google/protobuf
|
||||
DEPENDS:=+zlib +libpthread +libatomic +libstdcpp
|
||||
MAINTAINER:=Ken Keys <kkeys@caida.org>
|
||||
endef
|
||||
|
||||
define Package/protobuf
|
||||
$(call Package/protobuf/Default)
|
||||
DEPENDS+=+protobuf-lite
|
||||
endef
|
||||
|
||||
define Package/protobuf-lite
|
||||
$(call Package/protobuf/Default)
|
||||
endef
|
||||
|
||||
define Package/protobuf/description/Default
|
||||
Protocol Buffers are a way of encoding structured data in an efficient
|
||||
yet extensible format. Google uses Protocol Buffers for almost all
|
||||
of its internal RPC protocols and file formats.
|
||||
endef
|
||||
|
||||
define Package/protobuf/description
|
||||
$(call Package/protobuf/description/Default)
|
||||
|
||||
This package provides the libprotoc, libprotobuf, and libprotobuf-lite
|
||||
libraries. For a much smaller protobuf package, see "protobuf-lite".
|
||||
|
||||
endef
|
||||
|
||||
define Package/protobuf-lite/description
|
||||
$(call Package/protobuf/description/Default)
|
||||
|
||||
This package provides the libprotobuf-lite library.
|
||||
|
||||
endef
|
||||
|
||||
EXTRA_CPPFLAGS+=-std=c++11
|
||||
CONFIGURE_ARGS += --with-protoc=$(STAGING_DIR_HOSTPKG)/bin/protoc
|
||||
|
||||
define Build/InstallDev
|
||||
$(INSTALL_DIR) \
|
||||
$(1)/usr/lib \
|
||||
$(1)/usr/include
|
||||
|
||||
$(CP) \
|
||||
$(PKG_INSTALL_DIR)/usr/include/* \
|
||||
$(1)/usr/include/
|
||||
|
||||
$(CP) \
|
||||
$(PKG_INSTALL_DIR)/usr/lib/* \
|
||||
$(1)/usr/lib/
|
||||
endef
|
||||
|
||||
define Package/protobuf-lite/install
|
||||
$(INSTALL_DIR) \
|
||||
$(1)/usr/lib
|
||||
|
||||
$(CP) \
|
||||
$(PKG_INSTALL_DIR)/usr/lib/libprotobuf-lite.so* \
|
||||
$(1)/usr/lib/
|
||||
endef
|
||||
|
||||
define Package/protobuf/install
|
||||
$(INSTALL_DIR) \
|
||||
$(1)/usr/lib
|
||||
|
||||
$(CP) \
|
||||
$(PKG_INSTALL_DIR)/usr/lib/libprotoc.so* \
|
||||
$(1)/usr/lib/
|
||||
|
||||
$(CP) \
|
||||
$(PKG_INSTALL_DIR)/usr/lib/libprotobuf.so* \
|
||||
$(1)/usr/lib/
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,protobuf))
|
||||
$(eval $(call BuildPackage,protobuf-lite))
|
||||
$(eval $(call HostBuild))
|
||||
@@ -6,6 +6,7 @@ PKG_SOURCE_PROTO:=git
|
||||
PKG_BRANCH:=master
|
||||
PKG_RELEASE:=2
|
||||
PKG_SOURCE_URL:=https://source.codeaurora.org/quic/qsdk/oss/lklm/nss-clients/
|
||||
PKG_MIRROR_HASH:=802bf8b2dac8da0549e108b873afd982d127370c07d6574ece71f902eafe7698
|
||||
PKG_VERSION:=153998d70fdba508a59a28c13a606032cbf32686
|
||||
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||
|
||||
11
feeds/ipq807x/qca-nss-drv/patches/200-napi_threaded.patch
Normal file
11
feeds/ipq807x/qca-nss-drv/patches/200-napi_threaded.patch
Normal file
@@ -0,0 +1,11 @@
|
||||
--- a/nss_hal/nss_hal.c
|
||||
+++ b/nss_hal/nss_hal.c
|
||||
@@ -306,6 +306,8 @@ int nss_hal_probe(struct platform_device
|
||||
* Initialize the dummy netdevice.
|
||||
*/
|
||||
init_dummy_netdev(&nss_ctx->napi_ndev);
|
||||
+ strcpy(nss_ctx->napi_ndev.name, "nss");
|
||||
+ nss_ctx->napi_ndev.threaded = 1;
|
||||
|
||||
for (i = 0; i < npd->num_irq; i++) {
|
||||
err = nss_hal_register_irq(nss_ctx, npd, &nss_ctx->napi_ndev, i);
|
||||
55
feeds/ipq807x/wireguard/Makefile
Normal file
55
feeds/ipq807x/wireguard/Makefile
Normal file
@@ -0,0 +1,55 @@
|
||||
#
|
||||
# Copyright (C) 2016-2019 Jason A. Donenfeld <Jason@zx2c4.com>
|
||||
# Copyright (C) 2016 Baptiste Jonglez <openwrt@bitsofnetworks.org>
|
||||
# Copyright (C) 2016-2017 Dan Luedtke <mail@danrl.com>
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
include $(INCLUDE_DIR)/kernel.mk
|
||||
|
||||
PKG_NAME:=wireguard-backport
|
||||
|
||||
PKG_VERSION:=1.0.20211208
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE:=wireguard-linux-compat-$(PKG_VERSION).tar.xz
|
||||
PKG_SOURCE_URL:=https://git.zx2c4.com/wireguard-linux-compat/snapshot/
|
||||
PKG_HASH:=c0e607138a17daac656f508d8e63ea3737b5221fa5d9288191ddeb099f5a3b92
|
||||
|
||||
PKG_LICENSE:=GPL-2.0
|
||||
PKG_LICENSE_FILES:=COPYING
|
||||
|
||||
PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/wireguard-linux-compat-$(PKG_VERSION)
|
||||
PKG_BUILD_PARALLEL:=1
|
||||
PKG_USE_MIPS16:=0
|
||||
|
||||
# WireGuard's makefile needs this to know where to build the kernel module
|
||||
export KERNELDIR:=$(LINUX_DIR)
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
include $(INCLUDE_DIR)/kernel-defaults.mk
|
||||
include $(INCLUDE_DIR)/package-defaults.mk
|
||||
|
||||
define Build/Compile
|
||||
$(MAKE) $(KERNEL_MAKEOPTS) M="$(PKG_BUILD_DIR)/src" modules
|
||||
endef
|
||||
|
||||
define KernelPackage/wireguard-backport
|
||||
SECTION:=kernel
|
||||
CATEGORY:=Kernel modules
|
||||
SUBMENU:=Network Support
|
||||
TITLE:=WireGuard kernel module
|
||||
DEPENDS:=+IPV6:kmod-udptunnel6 +kmod-udptunnel4
|
||||
FILES:= $(PKG_BUILD_DIR)/src/wireguard.$(LINUX_KMOD_SUFFIX)
|
||||
AUTOLOAD:=$(call AutoProbe,wireguard)
|
||||
endef
|
||||
|
||||
define KernelPackage/wireguard-backport/description
|
||||
$(call Package/wireguard/Default/description)
|
||||
|
||||
This package provides the kernel module for WireGuard.
|
||||
endef
|
||||
|
||||
$(eval $(call KernelPackage,wireguard-backport))
|
||||
29
feeds/ipq807x/wireguard/patches/100-compat.patch
Normal file
29
feeds/ipq807x/wireguard/patches/100-compat.patch
Normal file
@@ -0,0 +1,29 @@
|
||||
Index: wireguard-linux-compat-1.0.20211208/src/compat/compat.h
|
||||
===================================================================
|
||||
--- wireguard-linux-compat-1.0.20211208.orig/src/compat/compat.h
|
||||
+++ wireguard-linux-compat-1.0.20211208/src/compat/compat.h
|
||||
@@ -11,6 +11,8 @@
|
||||
#include <linux/types.h>
|
||||
#include <generated/utsrelease.h>
|
||||
|
||||
+#define fallthrough
|
||||
+
|
||||
#ifdef RHEL_MAJOR
|
||||
#if RHEL_MAJOR == 7
|
||||
#define ISRHEL7
|
||||
@@ -686,15 +688,6 @@ struct __compat_dummy_container { char d
|
||||
#define genl_dump_check_consistent(a, b) genl_dump_check_consistent(a, b, &genl_family)
|
||||
#endif
|
||||
|
||||
-#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0) && !defined(ISRHEL7)
|
||||
-static inline void *skb_put_data(struct sk_buff *skb, const void *data, unsigned int len)
|
||||
-{
|
||||
- void *tmp = skb_put(skb, len);
|
||||
- memcpy(tmp, data, len);
|
||||
- return tmp;
|
||||
-}
|
||||
-#endif
|
||||
-
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0) && !defined(ISRHEL7)
|
||||
#define napi_complete_done(n, work_done) napi_complete(n)
|
||||
#endif
|
||||
@@ -2,23 +2,75 @@
|
||||
|
||||
START=80
|
||||
|
||||
copy_certificates() {
|
||||
[ -f /certificates/dev-id ] || return
|
||||
|
||||
cp /certificates/*.pem /etc/ucentral/
|
||||
cp /certificates/dev-id /etc/ucentral/
|
||||
chown root.network /etc/ucentral/*.pem
|
||||
chmod 0440 root.network /etc/ucentral/*.pem
|
||||
chmod 0400 /etc/ucentral/dev-id
|
||||
exit 0
|
||||
}
|
||||
|
||||
boot() {
|
||||
[ -f /etc/ucentral/dev-id ] && return
|
||||
. /lib/functions.sh
|
||||
mkdir -p /certificates /etc/ucentral/
|
||||
local mtd=$(find_mtd_index certificates)
|
||||
[ -n "$mtd" -a -f /sys/class/mtd/mtd$mtd/oobsize ] && ubiattach -p /dev/mtd$mtd
|
||||
if [ -n "$(ubinfo -a | grep certificates)" ]; then
|
||||
[ -e /dev/ubi0 ] && mount -t ubifs ubi0:certificates /certificates
|
||||
[ -e /dev/ubi1 ] && mount -t ubifs ubi1:certificates /certificates
|
||||
else
|
||||
|
||||
if [ "$(head -c 4 /dev/mtd$mtd)" == "hsqs" ]; then
|
||||
mount -t squashfs /dev/mtdblock$mtd /certificates
|
||||
else
|
||||
[ -n "$mtd" -a -f /sys/class/mtd/mtd$mtd/oobsize ] && ubiattach -p /dev/mtd$mtd
|
||||
if [ -n "$(ubinfo -a | grep certificates)" ]; then
|
||||
[ -e /dev/ubi0 ] && mount -t ubifs ubi0:certificates /certificates
|
||||
[ -e /dev/ubi1 ] && mount -t ubifs ubi1:certificates /certificates
|
||||
fi
|
||||
fi
|
||||
[ -f /certificates/dev-id ] && {
|
||||
cp /certificates/*.pem /etc/ucentral/
|
||||
cp /certificates/dev-id /etc/ucentral/
|
||||
chown root.network /etc/ucentral/*.pem
|
||||
chmod 0440 root.network /etc/ucentral/*.pem
|
||||
chmod 0400 /etc/ucentral/dev-id
|
||||
}
|
||||
copy_certificates
|
||||
|
||||
# if we get here no valid certificates were found
|
||||
|
||||
. /lib/functions.sh
|
||||
|
||||
local PART_NAME
|
||||
|
||||
case "$(board_name)" in
|
||||
actiontec,web7200)
|
||||
if grep -q bootselect=0 /proc/cmdline; then
|
||||
PART_NAME=firmware2
|
||||
else
|
||||
PART_NAME=firmware1
|
||||
fi
|
||||
;;
|
||||
edgecore,ecw5211|\
|
||||
edgecore,eap101|\
|
||||
edgecore,eap102)
|
||||
if grep -q rootfs1 /proc/cmdline; then
|
||||
PART_NAME=rootfs2
|
||||
else
|
||||
PART_NAME=rootfs1
|
||||
fi
|
||||
;;
|
||||
hfcl,ion4xi|\
|
||||
hfcl,ion4xe)
|
||||
if grep -q rootfs_1 /proc/cmdline; then
|
||||
PART_NAME=rootfs
|
||||
else
|
||||
PART_NAME=rootfs_1
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
|
||||
local MTD=$(find_mtd_index $PART_NAME)
|
||||
|
||||
[ -z "$MTD" ] && return 1
|
||||
|
||||
ubiattach -m $MTD -d 3
|
||||
[ -e /dev/ubi3 ] && mount -t ubifs ubi3:certificates /certificates
|
||||
copy_certificates
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ generate_certificate_volume() {
|
||||
ubinfo /dev/ubi0 -N certificates > /dev/null
|
||||
[ $? -eq 0 ] || {
|
||||
ubirsvol /dev/ubi0 -N rootfs_data -s 20MiB
|
||||
ubimkvol /dev/ubi0 -N certificates -s 2MiB
|
||||
ubimkvol /dev/ubi0 -N certificates -S 20
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,13 +8,13 @@ PROG=/usr/bin/ucode
|
||||
start_service() {
|
||||
[ -f /etc/ucentral/capabilities.json ] || {
|
||||
mkdir -p /etc/ucentral/
|
||||
ucode -m ubus -E board=/etc/board.json /usr/share/ucentral/capabilities.uc > /etc/ucentral/capabilities.json
|
||||
/usr/share/ucentral/capabilities.uc
|
||||
}
|
||||
|
||||
/usr/share/ucentral/ucentral.uc /etc/ucentral/ucentral.cfg.0000000001 > /dev/null
|
||||
|
||||
procd_open_instance
|
||||
procd_set_param command "$PROG" -m uci -m fs -i /usr/share/ucentral/firstcontact.uc
|
||||
procd_set_param command "$PROG" -l uci -l fs /usr/share/ucentral/firstcontact.uc
|
||||
procd_set_param respawn 1 10 0
|
||||
procd_close_instance
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
{%
|
||||
let devid;
|
||||
let fd = fs.open("/etc/ucentral/dev-id", "r");
|
||||
if (!fd) {
|
||||
@@ -62,4 +61,3 @@ system("/etc/init.d/firstcontact disable");
|
||||
system("reload_config");
|
||||
system("/etc/init.d/ucentral start");
|
||||
system("/etc/init.d/firstcontact stop");
|
||||
%}
|
||||
|
||||
@@ -16,12 +16,14 @@ wifi config
|
||||
|
||||
. /lib/functions.sh
|
||||
|
||||
SUFFIX=$(uci get system.@system[0].hostname | tail -c 7 | tr a-f A-F | tr -d '\n')
|
||||
|
||||
radio_enable() {
|
||||
uci set wireless.$1.disabled=0
|
||||
}
|
||||
|
||||
ssid_set() {
|
||||
uci set wireless.$1.ssid='Maverick'
|
||||
uci set wireless.$1.ssid=Maverick-${SUFFIX}
|
||||
}
|
||||
|
||||
delete_forwarding() {
|
||||
|
||||
@@ -4,6 +4,7 @@ PKG_NAME:=dynamic-vlan
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE_URL=https://github.com/blogic/dynamic-vlan.git
|
||||
PKG_MIRROR_HASH:=448890cdf182bd1b47edffca242e607594d0d17f6f5017a6fd021aab79f3c351
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_DATE:=2021-06-04
|
||||
PKG_SOURCE_VERSION:=55d78d3e7215b601084980d922349bcfdcf9cf20
|
||||
|
||||
@@ -7,6 +7,7 @@ PKG_LICENSE:=GPL-2.0
|
||||
PKG_MAINTAINER:=John Crispin <john@phrozen.org>
|
||||
|
||||
PKG_SOURCE_URL=https://github.com/blogic/ieee8021x.git
|
||||
PKG_MIRROR_HASH:=7e14e320714b4759f5c393f90165a69d133633612b57d408b3ab6535710bf53c
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_DATE:=2021-04-12
|
||||
PKG_SOURCE_VERSION:=c1f36559dc0ed2deeac0531a3d5854f1955ae928
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (C) 2008-2012 OpenWrt.org
|
||||
# Copyright (C) 2021 OpenWrt.org
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
@@ -9,26 +9,31 @@ include $(TOPDIR)/rules.mk
|
||||
include $(INCLUDE_DIR)/kernel.mk
|
||||
|
||||
PKG_NAME:=qosify
|
||||
PKG_RELEASE:=1
|
||||
PKG_SOURCE_URL=$(PROJECT_GIT)/project/qosify.git
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_DATE:=2022-03-06
|
||||
PKG_SOURCE_VERSION:=f13b67c9a786567df240a8f3f608e2724ddaadba
|
||||
PKG_MIRROR_HASH:=3d8629e711e46a6be79a46a6394165fd1761687f24b8ed954dc4f16f177cd90f
|
||||
PKG_RELEASE:=$(AUTORELEASE)
|
||||
|
||||
PKG_LICENSE:=GPL-2.0
|
||||
PKG_MAINTAINER:=Felix Fietkau <nbd@nbd.name>
|
||||
|
||||
PKG_BUILD_DEPENDS:=bpf-headers
|
||||
PKG_FLAGS:=nonshared
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
include $(INCLUDE_DIR)/cmake.mk
|
||||
include $(INCLUDE_DIR)/bpf.mk
|
||||
include $(INCLUDE_DIR)/nls.mk
|
||||
|
||||
define Package/qosify
|
||||
SECTION:=kernel
|
||||
CATEGORY:=Kernel modules
|
||||
SUBMENU:=Network Support
|
||||
TITLE:=QoS classifier eBPF module
|
||||
DEPENDS:=+libbpf +libubox +libubus +kmod-sched-cake +tc-full
|
||||
PKGFLAGS+=nonshared
|
||||
SECTION:=utils
|
||||
CATEGORY:=Base system
|
||||
TITLE:=A simple QoS solution based eBPF + CAKE
|
||||
DEPENDS:=+libbpf +libubox +libubus +kmod-sched-cake +kmod-sched-bpf +kmod-ifb +tc-full $(BPF_DEPENDS)
|
||||
endef
|
||||
|
||||
BPF_DOC = $(wildcard $(patsubst %,$(BPF_HEADERS_DIR)/scripts/%.py,bpf_doc bpf_helpers_doc))
|
||||
|
||||
define Build/Compile
|
||||
$(call CompileBPF,$(PKG_BUILD_DIR)/qosify-bpf.c)
|
||||
$(Build/Compile/Default)
|
||||
@@ -36,17 +41,28 @@ endef
|
||||
|
||||
define Package/qosify/conffiles
|
||||
/etc/config/qosify
|
||||
/etc/qosify-defaults.conf
|
||||
/etc/qosify/00-defaults.conf
|
||||
endef
|
||||
|
||||
define Package/qosify/install
|
||||
$(INSTALL_DIR) $(1)/lib/bpf $(1)/usr/sbin $(1)/etc/init.d $(1)/etc/config $(1)/etc/hotplug.d/net
|
||||
$(INSTALL_DIR) \
|
||||
$(1)/lib/bpf \
|
||||
$(1)/usr/sbin \
|
||||
$(1)/etc/init.d \
|
||||
$(1)/etc/config \
|
||||
$(1)/etc/qosify \
|
||||
$(1)/etc/hotplug.d/net \
|
||||
$(1)/etc/hotplug.d/iface
|
||||
$(INSTALL_DATA) $(PKG_BUILD_DIR)/qosify-bpf.o $(1)/lib/bpf
|
||||
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/qosify $(1)/usr/sbin/
|
||||
$(INSTALL_BIN) \
|
||||
$(PKG_INSTALL_DIR)/usr/bin/qosify \
|
||||
./files/qosify-status \
|
||||
$(1)/usr/sbin/
|
||||
$(INSTALL_BIN) ./files/qosify.init $(1)/etc/init.d/qosify
|
||||
$(INSTALL_DATA) ./files/qosify-defaults.conf $(1)/etc/qosify-defaults.conf
|
||||
$(INSTALL_DATA) ./files/qosify-defaults.conf $(1)/etc/qosify/00-defaults.conf
|
||||
$(INSTALL_DATA) ./files/qosify.conf $(1)/etc/config/qosify
|
||||
$(INSTALL_DATA) ./files/qosify.hotplug $(1)/etc/hotplug.d/net/10-qosify
|
||||
$(INSTALL_DATA) ./files/qosify.hotplug $(1)/etc/hotplug.d/iface/10-qosify
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,qosify))
|
||||
|
||||
Binary file not shown.
@@ -1,17 +1,17 @@
|
||||
# DNS
|
||||
tcp:53 CS5
|
||||
tcp:5353 CS5
|
||||
udp:53 CS5
|
||||
udp:5353 CS5
|
||||
tcp:53 voice
|
||||
tcp:5353 voice
|
||||
udp:53 voice
|
||||
udp:5353 voice
|
||||
|
||||
# NTP
|
||||
udp:123 CS6
|
||||
udp:123 voice
|
||||
|
||||
# SSH
|
||||
tcp:22 +CS4
|
||||
tcp:22 +video
|
||||
|
||||
# HTTP/QUIC
|
||||
tcp:80 +CS3
|
||||
tcp:443 +CS3
|
||||
udp:80 +CS3
|
||||
udp:443 +CS3
|
||||
tcp:80 +besteffort
|
||||
tcp:443 +besteffort
|
||||
udp:80 +besteffort
|
||||
udp:443 +besteffort
|
||||
|
||||
70
feeds/ucentral/qosify/files/qosify-status
Normal file
70
feeds/ucentral/qosify/files/qosify-status
Normal file
@@ -0,0 +1,70 @@
|
||||
#!/bin/sh
|
||||
. /usr/share/libubox/jshn.sh
|
||||
|
||||
dev_status() {
|
||||
tc -s qdisc sh dev "$1" root
|
||||
echo
|
||||
}
|
||||
|
||||
common_status() {
|
||||
json_get_vars ifname ingress egress
|
||||
|
||||
[ -n "$ifname" ] || return
|
||||
|
||||
[ "$egress" -gt 0 ] && {
|
||||
echo "egress status:"
|
||||
dev_status "$ifname"
|
||||
}
|
||||
[ "$ingress" -gt 0 ] && {
|
||||
echo "ingress status:"
|
||||
dev_status "$(printf %.16s "ifb-$ifname")"
|
||||
}
|
||||
}
|
||||
|
||||
is_active() {
|
||||
json_get_vars active
|
||||
|
||||
[ "${active:-0}" -gt 0 ]
|
||||
}
|
||||
|
||||
device_status() {
|
||||
local name="$2"
|
||||
|
||||
json_select "$name"
|
||||
|
||||
if is_active; then
|
||||
status="active"
|
||||
else
|
||||
status="not found"
|
||||
fi
|
||||
|
||||
echo "===== device $name: $status ====="
|
||||
|
||||
is_active && common_status
|
||||
|
||||
json_select ..
|
||||
}
|
||||
|
||||
interface_status() {
|
||||
local name="$2"
|
||||
|
||||
json_select "$name"
|
||||
|
||||
if is_active; then
|
||||
status="active"
|
||||
elif ubus -S -t 0 wait_for "network.interface.$name"; then
|
||||
status="down"
|
||||
else
|
||||
status="not found"
|
||||
fi
|
||||
|
||||
echo "===== interface $name: $status ====="
|
||||
|
||||
is_active && common_status
|
||||
|
||||
json_select ..
|
||||
}
|
||||
|
||||
json_load "$(ubus call qosify status)"
|
||||
json_for_each_item device_status devices
|
||||
json_for_each_item interface_status interfaces
|
||||
@@ -1,24 +1,42 @@
|
||||
config defaults
|
||||
list defaults /etc/qosify-defaults.conf
|
||||
option dscp_prio CS5
|
||||
option dscp_icmp CS6
|
||||
option dscp_bulk CS0
|
||||
option dscp_default_udp CS4
|
||||
option bulk_trigger_timeout 5
|
||||
option bulk_trigger_pps 100
|
||||
list defaults /etc/qosify/*.conf
|
||||
option dscp_prio video
|
||||
option dscp_icmp +besteffort
|
||||
option dscp_default_udp besteffort
|
||||
option prio_max_avg_pkt_len 500
|
||||
|
||||
config class besteffort
|
||||
option ingress CS0
|
||||
option egress CS0
|
||||
|
||||
config class bulk
|
||||
option ingress LE
|
||||
option egress LE
|
||||
|
||||
config class video
|
||||
option ingress AF41
|
||||
option egress AF41
|
||||
|
||||
config class voice
|
||||
option ingress CS6
|
||||
option egress CS6
|
||||
option bulk_trigger_pps 100
|
||||
option bulk_trigger_timeout 5
|
||||
option dscp_bulk CS0
|
||||
|
||||
config interface wan
|
||||
option name wan
|
||||
option disabled 1
|
||||
option bandwidth_up 100mbit
|
||||
option bandwidth_down 100mbit
|
||||
option overhead_type none
|
||||
# defaults:
|
||||
option ingress 1
|
||||
option egress 1
|
||||
option mode diffserv4
|
||||
option nat 1
|
||||
option host_isolate 1
|
||||
option autorate_ingress 1
|
||||
option autorate_ingress 0
|
||||
option ingress_options ""
|
||||
option egress_options ""
|
||||
option options ""
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
# Copyright (c) 2014 OpenWrt.org
|
||||
# Copyright (c) 2021 OpenWrt.org
|
||||
|
||||
START=19
|
||||
|
||||
@@ -15,6 +15,16 @@ add_option() {
|
||||
[ -n "$val" ] && json_add_$type "$name" "$val"
|
||||
}
|
||||
|
||||
add_flow_config() {
|
||||
local cfg="$1"
|
||||
|
||||
add_option string dscp_prio
|
||||
add_option string dscp_bulk
|
||||
add_option int bulk_trigger_timeout
|
||||
add_option int bulk_trigger_pps
|
||||
add_option int prio_max_avg_pkt_len
|
||||
}
|
||||
|
||||
add_defaults() {
|
||||
cfg="$1"
|
||||
|
||||
@@ -27,15 +37,11 @@ add_defaults() {
|
||||
done
|
||||
json_close_array
|
||||
|
||||
add_flow_config "$cfg"
|
||||
add_option int timeout
|
||||
add_option string dscp_prio
|
||||
add_option string dscp_bulk
|
||||
add_option string dscp_icmp
|
||||
add_option string dscp_default_udp
|
||||
add_option string dscp_default_tcp
|
||||
add_option int bulk_trigger_timeout
|
||||
add_option int bulk_trigger_pps
|
||||
add_option int prio_max_avg_pkt_len
|
||||
}
|
||||
|
||||
add_interface() {
|
||||
@@ -57,19 +63,74 @@ add_interface() {
|
||||
bw_down="${bw_down:-$bw}"
|
||||
[ -n "$bw_down" ] && json_add_string bandwidth_down "$bw_down"
|
||||
|
||||
add_option string bandwidth
|
||||
add_option string bandwidth
|
||||
add_option boolean ingress
|
||||
add_option boolean egress
|
||||
add_option string mode
|
||||
add_option boolean host_isolate
|
||||
add_option boolean nat
|
||||
add_option boolean host_isolate
|
||||
add_option boolean autorate_ingress
|
||||
add_option string ingress_options
|
||||
add_option string egress_options
|
||||
add_option string options
|
||||
|
||||
config_get user_options "$cfg" options
|
||||
|
||||
config_get otype "$cfg" overhead_type
|
||||
options=
|
||||
case "$otype" in
|
||||
none);;
|
||||
manual)
|
||||
config_get overhead "$cfg" overhead
|
||||
[ -n "$overhead" ] && append options "overhead $overhead"
|
||||
|
||||
config_get encap "$cfg" overhead_encap
|
||||
[ -n "$encap" ] && append options "$encap"
|
||||
;;
|
||||
conservative|\
|
||||
pppoa-vcmux|\
|
||||
pppoa-llc|\
|
||||
pppoe-vcmux|\
|
||||
pppoe-llcsnap|\
|
||||
bridged-vcmux|\
|
||||
bridged-llcsnap|\
|
||||
ipoa-vcmux|\
|
||||
ipoa-llcsnap|\
|
||||
pppoe-ptm|\
|
||||
bridged-ptm|\
|
||||
docsis|\
|
||||
ethernet)
|
||||
append options "$otype"
|
||||
;;
|
||||
esac
|
||||
|
||||
config_get mpu "$cfg" overhead_mpu
|
||||
[ -n "$mpu" ] && append options "mpu $mpu"
|
||||
|
||||
config_get ovlan "$cfg" overhead_vlan
|
||||
[ "${ovlan:-0}" -ge 2 ] && append options "ether-vlan"
|
||||
[ "${ovlan:-0}" -ge 1 ] && append options "ether-vlan"
|
||||
|
||||
[ -n "$user_options" ] && append options "$user_options"
|
||||
[ -n "$options" ] && json_add_string options "$options"
|
||||
|
||||
json_close_object
|
||||
}
|
||||
|
||||
add_class() {
|
||||
local cfg="$1"
|
||||
|
||||
config_get value "$cfg" value
|
||||
config_get ingress "$cfg" ingress
|
||||
config_get egress "$cfg" egress
|
||||
|
||||
json_add_object "$cfg"
|
||||
json_add_string ingress "${ingress:-$value}"
|
||||
json_add_string egress "${egress:-$value}"
|
||||
add_flow_config "$cfg"
|
||||
json_close_object
|
||||
}
|
||||
|
||||
|
||||
reload_service() {
|
||||
json_init
|
||||
|
||||
@@ -81,6 +142,11 @@ reload_service() {
|
||||
config_foreach add_interface interface
|
||||
json_close_object
|
||||
|
||||
json_add_object classes
|
||||
config_foreach add_class class
|
||||
config_foreach add_class alias
|
||||
json_close_object
|
||||
|
||||
json_add_object devices
|
||||
config_foreach add_interface device
|
||||
json_close_object
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
PROJECT(qosify C)
|
||||
|
||||
ADD_DEFINITIONS(-Os -Wall -Wno-unknown-warning-option -Wno-array-bounds -Wno-format-truncation -Werror --std=gnu99)
|
||||
|
||||
SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
|
||||
|
||||
find_library(bpf NAMES bpf)
|
||||
ADD_EXECUTABLE(qosify main.c loader.c map.c ubus.c interface.c)
|
||||
TARGET_LINK_LIBRARIES(qosify ${bpf} ubox ubus)
|
||||
|
||||
INSTALL(TARGETS qosify
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_SBINDIR}
|
||||
)
|
||||
@@ -1,112 +0,0 @@
|
||||
QoSify is simple daemon for setting up and managing CAKE along with a custom
|
||||
eBPF based classifier that sets DSCP fields of packets.
|
||||
|
||||
It supports the following features:
|
||||
- simple TCP/UDP port based mapping
|
||||
- IP address based mapping
|
||||
- priority boosting based on average packet size
|
||||
- bulk flow detection based on number of packets per second
|
||||
- dynamically add IP entries with timeout
|
||||
- dns regex entries and ubus api for providing dns lookup results
|
||||
|
||||
It can be configured via ubus call qosify config.
|
||||
|
||||
This call supports the following parameters:
|
||||
- "reset": BOOL
|
||||
Reset the config to defaults instead of only updating supplied values
|
||||
|
||||
- "files": ARRAY of STRING
|
||||
List of files with port/IP/host mappings
|
||||
|
||||
- "timeout": INT32
|
||||
Default timeout for dynamically added entries
|
||||
|
||||
- "dscp_default_udp": STRING
|
||||
Default DSCP value for UDP packets
|
||||
|
||||
- "dscp_default_tcp": STRING
|
||||
Default DSCP value for TCP packets
|
||||
|
||||
- "dscp_prio": STRING
|
||||
DSCP value for priority-marked packets
|
||||
|
||||
- "dscp_bulk": STRING
|
||||
DSCP value for bulk-marked packets
|
||||
|
||||
- "dscp_icmp": STRING
|
||||
DSCP value for ICMP packets
|
||||
|
||||
- "bulk_trigger_pps": INT32
|
||||
Number of packets per second to trigger bulk flow detection
|
||||
|
||||
- "bulk_trigger_timeout": INT32
|
||||
Time below bulk_trigger_pps threshold until a bulk flow mark is removed
|
||||
|
||||
- "prio_max_avg_pkt_len": INT32
|
||||
Maximum average packet length for marking a flow as priority
|
||||
|
||||
- "interfaces": TABLE of TABLE
|
||||
netifd interfaces to enable QoS on
|
||||
|
||||
- "devices": TABLE of TABLE
|
||||
netdevs to enable QoS on
|
||||
|
||||
|
||||
interface/device properties:
|
||||
- "bandwidth_up": STRING
|
||||
Uplink bandwidth (same format as tc)
|
||||
|
||||
- "bandwidth_down": STRING
|
||||
Downlink bandwidth (same format as tc)
|
||||
|
||||
- "ingress": BOOL
|
||||
Enable ingress shaping
|
||||
|
||||
- "egress": BOOL
|
||||
Enable egress shaping
|
||||
|
||||
- "mode": STRING
|
||||
CAKE diffserv mode
|
||||
|
||||
- "nat": BOOL
|
||||
Enable CAKE NAT host detection via conntrack
|
||||
|
||||
- "host_isolate": BOOL
|
||||
Enable CAKE host isolation
|
||||
|
||||
- "autorate_ingress": BOOL
|
||||
Enable CAKE automatic rate estimation for ingress
|
||||
|
||||
- "ingress_options": STRING
|
||||
CAKE ingress options
|
||||
|
||||
- "egress_options": STRING
|
||||
CAKE egress options
|
||||
|
||||
- "options": STRING
|
||||
CAKE options for ingress + egress
|
||||
|
||||
|
||||
Mapping file syntax:
|
||||
|
||||
Each line has two whitespace separated fields, match and dscp
|
||||
match is one of:
|
||||
- tcp:<port>[-<endport>]
|
||||
TCP single port, or range from <port> to <endport>
|
||||
- udp:<port>[-<endport>]
|
||||
UDP single port, or range from <port> to <endport>
|
||||
- <ipaddr>
|
||||
IPv4 address, e.g. 1.1.1.1
|
||||
- <ipv6addr>
|
||||
IPv6 address, e.g. ff01::1
|
||||
- dns:<regex>
|
||||
POSIX.2 extended regular expression for matching hostnames
|
||||
Only works, if dns lookups are passed to qosify via the add_dns_host ubus call.
|
||||
|
||||
dscp can be a raw value, or a codepoint like CS0
|
||||
Adding a + in front of the value tells qosify to only override the DSCP value if it is zero
|
||||
|
||||
|
||||
Planned features:
|
||||
- Integration with dnsmasq to support hostname pattern based DSCP marking
|
||||
- Support for LAN host based priority
|
||||
@@ -1,563 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2021 Felix Fietkau <nbd@nbd.name>
|
||||
*/
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <net/if_arp.h>
|
||||
#include <net/if.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <libubox/vlist.h>
|
||||
#include <libubox/avl-cmp.h>
|
||||
#include <libubox/uloop.h>
|
||||
|
||||
#include "qosify.h"
|
||||
|
||||
static void interface_update_cb(struct vlist_tree *tree,
|
||||
struct vlist_node *node_new,
|
||||
struct vlist_node *node_old);
|
||||
|
||||
static VLIST_TREE(devices, avl_strcmp, interface_update_cb, true, false);
|
||||
static VLIST_TREE(interfaces, avl_strcmp, interface_update_cb, true, false);
|
||||
static int socket_fd;
|
||||
|
||||
#define APPEND(_buf, _ofs, _format, ...) _ofs += snprintf(_buf + _ofs, sizeof(_buf) - _ofs, _format, ##__VA_ARGS__)
|
||||
|
||||
struct qosify_iface_config {
|
||||
struct blob_attr *data;
|
||||
|
||||
bool ingress;
|
||||
bool egress;
|
||||
bool nat;
|
||||
bool host_isolate;
|
||||
bool autorate_ingress;
|
||||
|
||||
const char *bandwidth_up;
|
||||
const char *bandwidth_down;
|
||||
const char *mode;
|
||||
const char *common_opts;
|
||||
const char *ingress_opts;
|
||||
const char *egress_opts;
|
||||
};
|
||||
|
||||
|
||||
struct qosify_iface {
|
||||
struct vlist_node node;
|
||||
|
||||
char ifname[IFNAMSIZ];
|
||||
bool active;
|
||||
|
||||
bool device;
|
||||
struct blob_attr *config_data;
|
||||
struct qosify_iface_config config;
|
||||
};
|
||||
|
||||
enum {
|
||||
IFACE_ATTR_BW_UP,
|
||||
IFACE_ATTR_BW_DOWN,
|
||||
IFACE_ATTR_INGRESS,
|
||||
IFACE_ATTR_EGRESS,
|
||||
IFACE_ATTR_MODE,
|
||||
IFACE_ATTR_NAT,
|
||||
IFACE_ATTR_HOST_ISOLATE,
|
||||
IFACE_ATTR_AUTORATE_IN,
|
||||
IFACE_ATTR_INGRESS_OPTS,
|
||||
IFACE_ATTR_EGRESS_OPTS,
|
||||
IFACE_ATTR_OPTS,
|
||||
__IFACE_ATTR_MAX
|
||||
};
|
||||
|
||||
static inline const char *qosify_iface_name(struct qosify_iface *iface)
|
||||
{
|
||||
return iface->node.avl.key;
|
||||
}
|
||||
|
||||
static void
|
||||
iface_config_parse(struct blob_attr *attr, struct blob_attr **tb)
|
||||
{
|
||||
static const struct blobmsg_policy policy[__IFACE_ATTR_MAX] = {
|
||||
[IFACE_ATTR_BW_UP] = { "bandwidth_up", BLOBMSG_TYPE_STRING },
|
||||
[IFACE_ATTR_BW_DOWN] = { "bandwidth_down", BLOBMSG_TYPE_STRING },
|
||||
[IFACE_ATTR_INGRESS] = { "ingress", BLOBMSG_TYPE_BOOL },
|
||||
[IFACE_ATTR_EGRESS] = { "egress", BLOBMSG_TYPE_BOOL },
|
||||
[IFACE_ATTR_MODE] = { "mode", BLOBMSG_TYPE_STRING },
|
||||
[IFACE_ATTR_NAT] = { "nat", BLOBMSG_TYPE_BOOL },
|
||||
[IFACE_ATTR_HOST_ISOLATE] = { "host_isolate", BLOBMSG_TYPE_BOOL },
|
||||
[IFACE_ATTR_AUTORATE_IN] = { "autorate_ingress", BLOBMSG_TYPE_BOOL },
|
||||
[IFACE_ATTR_INGRESS_OPTS] = { "ingress_options", BLOBMSG_TYPE_STRING },
|
||||
[IFACE_ATTR_EGRESS_OPTS] = { "egress_options", BLOBMSG_TYPE_STRING },
|
||||
[IFACE_ATTR_OPTS] = { "options", BLOBMSG_TYPE_STRING },
|
||||
};
|
||||
|
||||
blobmsg_parse(policy, __IFACE_ATTR_MAX, tb, blobmsg_data(attr), blobmsg_len(attr));
|
||||
}
|
||||
|
||||
static bool
|
||||
iface_config_equal(struct qosify_iface *if1, struct qosify_iface *if2)
|
||||
{
|
||||
struct blob_attr *tb1[__IFACE_ATTR_MAX], *tb2[__IFACE_ATTR_MAX];
|
||||
int i;
|
||||
|
||||
iface_config_parse(if1->config_data, tb1);
|
||||
iface_config_parse(if2->config_data, tb2);
|
||||
|
||||
for (i = 0; i < __IFACE_ATTR_MAX; i++) {
|
||||
if (!!tb1[i] != !!tb2[i])
|
||||
return false;
|
||||
|
||||
if (!tb1[i])
|
||||
continue;
|
||||
|
||||
if (blob_raw_len(tb1[i]) != blob_raw_len(tb2[i]))
|
||||
return false;
|
||||
|
||||
if (memcmp(tb1[i], tb2[i], blob_raw_len(tb1[i])) != 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static const char *check_str(struct blob_attr *attr)
|
||||
{
|
||||
const char *str = blobmsg_get_string(attr);
|
||||
|
||||
if (strchr(str, '\''))
|
||||
return NULL;
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
static void
|
||||
iface_config_set(struct qosify_iface *iface, struct blob_attr *attr)
|
||||
{
|
||||
struct qosify_iface_config *cfg = &iface->config;
|
||||
struct blob_attr *tb[__IFACE_ATTR_MAX];
|
||||
struct blob_attr *cur;
|
||||
|
||||
iface_config_parse(attr, tb);
|
||||
|
||||
memset(cfg, 0, sizeof(*cfg));
|
||||
|
||||
/* defaults */
|
||||
cfg->mode = "diffserv4";
|
||||
cfg->ingress = true;
|
||||
cfg->egress = true;
|
||||
cfg->host_isolate = true;
|
||||
cfg->autorate_ingress = true;
|
||||
cfg->nat = !iface->device;
|
||||
|
||||
if ((cur = tb[IFACE_ATTR_BW_UP]) != NULL)
|
||||
cfg->bandwidth_up = check_str(cur);
|
||||
if ((cur = tb[IFACE_ATTR_BW_DOWN]) != NULL)
|
||||
cfg->bandwidth_down = check_str(cur);
|
||||
if ((cur = tb[IFACE_ATTR_MODE]) != NULL)
|
||||
cfg->mode = check_str(cur);
|
||||
if ((cur = tb[IFACE_ATTR_OPTS]) != NULL)
|
||||
cfg->common_opts = check_str(cur);
|
||||
if ((cur = tb[IFACE_ATTR_EGRESS_OPTS]) != NULL)
|
||||
cfg->egress_opts = check_str(cur);
|
||||
if ((cur = tb[IFACE_ATTR_INGRESS_OPTS]) != NULL)
|
||||
cfg->ingress_opts = check_str(cur);
|
||||
if ((cur = tb[IFACE_ATTR_INGRESS]) != NULL)
|
||||
cfg->ingress = blobmsg_get_bool(cur);
|
||||
if ((cur = tb[IFACE_ATTR_EGRESS]) != NULL)
|
||||
cfg->egress = blobmsg_get_bool(cur);
|
||||
if ((cur = tb[IFACE_ATTR_NAT]) != NULL)
|
||||
cfg->nat = blobmsg_get_bool(cur);
|
||||
if ((cur = tb[IFACE_ATTR_HOST_ISOLATE]) != NULL)
|
||||
cfg->host_isolate = blobmsg_get_bool(cur);
|
||||
if ((cur = tb[IFACE_ATTR_AUTORATE_IN]) != NULL)
|
||||
cfg->autorate_ingress = blobmsg_get_bool(cur);
|
||||
}
|
||||
|
||||
static const char *
|
||||
interface_ifb_name(struct qosify_iface *iface)
|
||||
{
|
||||
static char ifname[IFNAMSIZ + 1] = "ifb-";
|
||||
int len = strlen(iface->ifname);
|
||||
|
||||
if (len + 4 < IFNAMSIZ) {
|
||||
snprintf(ifname + 4, IFNAMSIZ - 4, "%s", iface->ifname);
|
||||
|
||||
return ifname;
|
||||
}
|
||||
|
||||
ifname[4] = iface->ifname[0];
|
||||
ifname[5] = iface->ifname[1];
|
||||
snprintf(ifname + 6, IFNAMSIZ - 6, "%s", iface->ifname + len - (IFNAMSIZ + 6) - 1);
|
||||
|
||||
return ifname;
|
||||
}
|
||||
|
||||
static int run_cmd(char *cmd, bool ignore)
|
||||
{
|
||||
char *argv[] = { "sh", "-c", cmd, NULL };
|
||||
bool first = true;
|
||||
int status = -1;
|
||||
char buf[512];
|
||||
int fds[2];
|
||||
FILE *f;
|
||||
int pid;
|
||||
|
||||
if (pipe(fds))
|
||||
return -1;
|
||||
|
||||
pid = fork();
|
||||
if (!pid) {
|
||||
close(fds[0]);
|
||||
if (fds[1] != STDOUT_FILENO)
|
||||
dup2(fds[1], STDOUT_FILENO);
|
||||
if (fds[1] != STDERR_FILENO)
|
||||
dup2(fds[1], STDERR_FILENO);
|
||||
if (fds[1] > STDERR_FILENO)
|
||||
close(fds[1]);
|
||||
execv("/bin/sh", argv);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (pid < 0)
|
||||
return -1;
|
||||
|
||||
close(fds[1]);
|
||||
f = fdopen(fds[0], "r");
|
||||
if (!f) {
|
||||
close(fds[0]);
|
||||
goto out;
|
||||
}
|
||||
|
||||
while (fgets(buf, sizeof(buf), f) != NULL) {
|
||||
if (!strlen(buf))
|
||||
break;
|
||||
if (ignore)
|
||||
continue;
|
||||
if (first) {
|
||||
ULOG_WARN("Command: %s\n", cmd);
|
||||
first = false;
|
||||
}
|
||||
ULOG_WARN("%s%s", buf, strchr(buf, '\n') ? "" : "\n");
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
|
||||
out:
|
||||
while (waitpid(pid, &status, 0) < 0)
|
||||
if (errno != EINTR)
|
||||
break;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int
|
||||
prepare_tc_cmd(char *buf, int len, const char *type, const char *cmd,
|
||||
const char *dev, const char *extra)
|
||||
{
|
||||
return snprintf(buf, len, "tc %s %s dev '%s' %s", type, cmd, dev, extra);
|
||||
}
|
||||
|
||||
static int
|
||||
cmd_del_qdisc(const char *ifname, const char *type)
|
||||
{
|
||||
char buf[64];
|
||||
|
||||
prepare_tc_cmd(buf, sizeof(buf), "qdisc", "del", ifname, type);
|
||||
|
||||
return run_cmd(buf, true);
|
||||
}
|
||||
|
||||
static int
|
||||
cmd_add_qdisc(struct qosify_iface *iface, const char *ifname, bool egress, bool eth)
|
||||
{
|
||||
struct qosify_iface_config *cfg = &iface->config;
|
||||
const char *bw = egress ? cfg->bandwidth_up : cfg->bandwidth_down;
|
||||
const char *dir_opts = egress ? cfg->egress_opts : cfg->ingress_opts;
|
||||
char buf[512];
|
||||
int ofs;
|
||||
|
||||
cmd_del_qdisc(ifname, "root");
|
||||
|
||||
ofs = prepare_tc_cmd(buf, sizeof(buf), "qdisc", "add", ifname, "root handle 1: cake");
|
||||
if (bw)
|
||||
APPEND(buf, ofs, " bandwidth %s", bw);
|
||||
|
||||
APPEND(buf, ofs, " %s %sgress", cfg->mode, egress ? "e" : "in");
|
||||
|
||||
if (cfg->host_isolate)
|
||||
APPEND(buf, ofs, " %snat dual-%shost",
|
||||
cfg->nat ? "" : "no",
|
||||
egress ? "src" : "dst");
|
||||
else
|
||||
APPEND(buf, ofs, " flows");
|
||||
|
||||
APPEND(buf, ofs, " %s %s",
|
||||
cfg->common_opts ? cfg->common_opts : "",
|
||||
dir_opts ? dir_opts : "");
|
||||
|
||||
run_cmd(buf, false);
|
||||
|
||||
ofs = prepare_tc_cmd(buf, sizeof(buf), "filter", "add", ifname, "parent 1: bpf");
|
||||
APPEND(buf, ofs, " object-pinned /sys/fs/bpf/qosify_%sgress_%s verbose direct-action",
|
||||
egress ? "e" : "in",
|
||||
eth ? "eth" : "ip");
|
||||
|
||||
return run_cmd(buf, false);
|
||||
}
|
||||
|
||||
static int
|
||||
cmd_del_ingress(struct qosify_iface *iface)
|
||||
{
|
||||
char buf[256];
|
||||
|
||||
cmd_del_qdisc(iface->ifname, "handle ffff: ingress");
|
||||
snprintf(buf, sizeof(buf), "ip link del '%s'", interface_ifb_name(iface));
|
||||
|
||||
return run_cmd(buf, true);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
cmd_add_ingress(struct qosify_iface *iface, bool eth)
|
||||
{
|
||||
const char *ifbdev = interface_ifb_name(iface);
|
||||
char buf[256];
|
||||
int ofs;
|
||||
|
||||
cmd_del_ingress(iface);
|
||||
|
||||
ofs = prepare_tc_cmd(buf, sizeof(buf), "qdisc", "add", iface->ifname, " handle ffff: ingress");
|
||||
run_cmd(buf, false);
|
||||
|
||||
snprintf(buf, sizeof(buf), "ip link add '%s' type ifb", ifbdev);
|
||||
run_cmd(buf, false);
|
||||
|
||||
cmd_add_qdisc(iface, ifbdev, false, eth);
|
||||
|
||||
snprintf(buf, sizeof(buf), "ip link set dev '%s' up", ifbdev);
|
||||
run_cmd(buf, false);
|
||||
|
||||
ofs = prepare_tc_cmd(buf, sizeof(buf), "filter", "add", iface->ifname, " parent ffff:");
|
||||
APPEND(buf, ofs, " protocol all prio 10 u32 match u32 0 0 "
|
||||
"flowid 1:1 action mirred egress redirect dev '%s'", ifbdev);
|
||||
return run_cmd(buf, false);
|
||||
}
|
||||
|
||||
static void
|
||||
interface_start(struct qosify_iface *iface)
|
||||
{
|
||||
struct ifreq ifr = {};
|
||||
bool eth;
|
||||
|
||||
if (!iface->ifname[0] || iface->active)
|
||||
return;
|
||||
|
||||
ULOG_INFO("start interface %s\n", iface->ifname);
|
||||
|
||||
strncpy(ifr.ifr_name, iface->ifname, sizeof(ifr.ifr_name));
|
||||
if (ioctl(socket_fd, SIOCGIFHWADDR, &ifr) < 0) {
|
||||
ULOG_ERR("ioctl(SIOCGIFHWADDR, %s) failed: %s\n", iface->ifname, strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
eth = ifr.ifr_hwaddr.sa_family == ARPHRD_ETHER;
|
||||
|
||||
if (iface->config.egress)
|
||||
cmd_add_qdisc(iface, iface->ifname, true, eth);
|
||||
if (iface->config.ingress)
|
||||
cmd_add_ingress(iface, eth);
|
||||
|
||||
iface->active = true;
|
||||
}
|
||||
|
||||
static void
|
||||
interface_stop(struct qosify_iface *iface)
|
||||
{
|
||||
if (!iface->ifname[0] || !iface->active)
|
||||
return;
|
||||
|
||||
ULOG_INFO("stop interface %s\n", iface->ifname);
|
||||
iface->active = false;
|
||||
|
||||
if (iface->config.egress)
|
||||
cmd_del_qdisc(iface->ifname, "root");
|
||||
if (iface->config.ingress)
|
||||
cmd_del_ingress(iface);
|
||||
}
|
||||
|
||||
static void
|
||||
interface_set_config(struct qosify_iface *iface, struct blob_attr *config)
|
||||
{
|
||||
iface->config_data = blob_memdup(config);
|
||||
iface_config_set(iface, iface->config_data);
|
||||
interface_start(iface);
|
||||
}
|
||||
|
||||
static void
|
||||
interface_update_cb(struct vlist_tree *tree,
|
||||
struct vlist_node *node_new, struct vlist_node *node_old)
|
||||
{
|
||||
struct qosify_iface *if_new = NULL, *if_old = NULL;
|
||||
|
||||
if (node_new)
|
||||
if_new = container_of(node_new, struct qosify_iface, node);
|
||||
if (node_old)
|
||||
if_old = container_of(node_old, struct qosify_iface, node);
|
||||
|
||||
if (if_new && if_old) {
|
||||
if (!iface_config_equal(if_old, if_new)) {
|
||||
interface_stop(if_old);
|
||||
free(if_old->config_data);
|
||||
interface_set_config(if_old, if_new->config_data);
|
||||
}
|
||||
|
||||
free(if_new);
|
||||
return;
|
||||
}
|
||||
|
||||
if (if_old) {
|
||||
interface_stop(if_old);
|
||||
free(if_old->config_data);
|
||||
free(if_old);
|
||||
}
|
||||
|
||||
if (if_new)
|
||||
interface_set_config(if_new, if_new->config_data);
|
||||
}
|
||||
|
||||
static void
|
||||
interface_create(struct blob_attr *attr, bool device)
|
||||
{
|
||||
struct qosify_iface *iface;
|
||||
const char *name = blobmsg_name(attr);
|
||||
int name_len = strlen(name);
|
||||
char *name_buf;
|
||||
|
||||
if (strchr(name, '\''))
|
||||
return;
|
||||
|
||||
if (name_len >= IFNAMSIZ)
|
||||
return;
|
||||
|
||||
if (blobmsg_type(attr) != BLOBMSG_TYPE_TABLE)
|
||||
return;
|
||||
|
||||
iface = calloc_a(sizeof(*iface), &name_buf, name_len + 1);
|
||||
strcpy(name_buf, blobmsg_name(attr));
|
||||
iface->config_data = attr;
|
||||
iface->device = device;
|
||||
vlist_add(device ? &devices : &interfaces, &iface->node, name_buf);
|
||||
}
|
||||
|
||||
void qosify_iface_config_update(struct blob_attr *ifaces, struct blob_attr *devs)
|
||||
{
|
||||
struct blob_attr *cur;
|
||||
int rem;
|
||||
|
||||
vlist_update(&devices);
|
||||
blobmsg_for_each_attr(cur, devs, rem)
|
||||
interface_create(cur, true);
|
||||
vlist_flush(&devices);
|
||||
|
||||
vlist_update(&interfaces);
|
||||
blobmsg_for_each_attr(cur, ifaces, rem)
|
||||
interface_create(cur, false);
|
||||
vlist_flush(&interfaces);
|
||||
}
|
||||
|
||||
static void
|
||||
qosify_iface_check_device(struct qosify_iface *iface)
|
||||
{
|
||||
const char *name = qosify_iface_name(iface);
|
||||
int ifindex;
|
||||
|
||||
ifindex = if_nametoindex(name);
|
||||
if (!ifindex) {
|
||||
interface_stop(iface);
|
||||
iface->ifname[0] = 0;
|
||||
} else {
|
||||
snprintf(iface->ifname, sizeof(iface->ifname), "%s", name);
|
||||
interface_start(iface);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
qosify_iface_check_interface(struct qosify_iface *iface)
|
||||
{
|
||||
const char *name = qosify_iface_name(iface);
|
||||
char ifname[IFNAMSIZ];
|
||||
|
||||
if (qosify_ubus_check_interface(name, ifname, sizeof(ifname)) == 0) {
|
||||
snprintf(iface->ifname, sizeof(iface->ifname), "%s", ifname);
|
||||
interface_start(iface);
|
||||
} else {
|
||||
interface_stop(iface);
|
||||
iface->ifname[0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void qos_iface_check_cb(struct uloop_timeout *t)
|
||||
{
|
||||
struct qosify_iface *iface;
|
||||
|
||||
vlist_for_each_element(&devices, iface, node)
|
||||
qosify_iface_check_device(iface);
|
||||
vlist_for_each_element(&interfaces, iface, node)
|
||||
qosify_iface_check_interface(iface);
|
||||
}
|
||||
|
||||
void qosify_iface_check(void)
|
||||
{
|
||||
static struct uloop_timeout timer = {
|
||||
.cb = qos_iface_check_cb,
|
||||
};
|
||||
|
||||
uloop_timeout_set(&timer, 10);
|
||||
}
|
||||
|
||||
void qosify_iface_status(struct blob_buf *b)
|
||||
{
|
||||
struct qosify_iface *iface;
|
||||
void *c, *i;
|
||||
|
||||
c = blobmsg_open_table(b, "devices");
|
||||
vlist_for_each_element(&devices, iface, node) {
|
||||
i = blobmsg_open_table(b, qosify_iface_name(iface));
|
||||
blobmsg_add_u8(b, "active", iface->active);
|
||||
blobmsg_close_table(b, i);
|
||||
}
|
||||
blobmsg_close_table(b, c);
|
||||
|
||||
c = blobmsg_open_table(b, "interfaces");
|
||||
vlist_for_each_element(&interfaces, iface, node) {
|
||||
i = blobmsg_open_table(b, qosify_iface_name(iface));
|
||||
blobmsg_add_u8(b, "active", iface->active);
|
||||
if (iface->ifname)
|
||||
blobmsg_add_string(b, "ifname", iface->ifname);
|
||||
blobmsg_close_table(b, i);
|
||||
}
|
||||
blobmsg_close_table(b, c);
|
||||
}
|
||||
|
||||
int qosify_iface_init(void)
|
||||
{
|
||||
socket_fd = socket(AF_UNIX, SOCK_DGRAM, 0);
|
||||
if (socket < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void qosify_iface_stop(void)
|
||||
{
|
||||
struct qosify_iface *iface;
|
||||
|
||||
vlist_for_each_element(&interfaces, iface, node)
|
||||
interface_stop(iface);
|
||||
vlist_for_each_element(&devices, iface, node)
|
||||
interface_stop(iface);
|
||||
}
|
||||
|
||||
@@ -1,121 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2021 Felix Fietkau <nbd@nbd.name>
|
||||
*/
|
||||
#include <sys/resource.h>
|
||||
#include <sys/stat.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <glob.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "qosify.h"
|
||||
|
||||
static int qosify_bpf_pr(enum libbpf_print_level level, const char *format,
|
||||
va_list args)
|
||||
{
|
||||
return vfprintf(stderr, format, args);
|
||||
}
|
||||
|
||||
static void qosify_init_env(void)
|
||||
{
|
||||
struct rlimit limit = {
|
||||
.rlim_cur = RLIM_INFINITY,
|
||||
.rlim_max = RLIM_INFINITY,
|
||||
};
|
||||
|
||||
setrlimit(RLIMIT_MEMLOCK, &limit);
|
||||
}
|
||||
|
||||
static void qosify_fill_rodata(struct bpf_object *obj, uint32_t flags)
|
||||
{
|
||||
struct bpf_map *map = NULL;
|
||||
|
||||
while ((map = bpf_map__next(map, obj)) != NULL) {
|
||||
if (!strstr(bpf_map__name(map), ".rodata"))
|
||||
continue;
|
||||
|
||||
bpf_map__set_initial_value(map, &flags, sizeof(flags));
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
qosify_create_program(const char *suffix, uint32_t flags)
|
||||
{
|
||||
DECLARE_LIBBPF_OPTS(bpf_object_open_opts, opts,
|
||||
.pin_root_path = CLASSIFY_DATA_PATH,
|
||||
);
|
||||
struct bpf_program *prog;
|
||||
struct bpf_object *obj;
|
||||
char path[256];
|
||||
int err;
|
||||
|
||||
snprintf(path, sizeof(path), CLASSIFY_PIN_PATH "_" "%s", suffix);
|
||||
|
||||
obj = bpf_object__open_file(CLASSIFY_PROG_PATH, &opts);
|
||||
err = libbpf_get_error(obj);
|
||||
if (err) {
|
||||
perror("bpf_object__open_file");
|
||||
return -1;
|
||||
}
|
||||
|
||||
prog = bpf_object__find_program_by_title(obj, "classifier");
|
||||
if (!prog) {
|
||||
fprintf(stderr, "Can't find classifier prog\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
bpf_program__set_type(prog, BPF_PROG_TYPE_SCHED_CLS);
|
||||
|
||||
qosify_fill_rodata(obj, flags);
|
||||
|
||||
err = bpf_object__load(obj);
|
||||
if (err) {
|
||||
perror("bpf_object__load");
|
||||
return -1;
|
||||
}
|
||||
|
||||
libbpf_set_print(NULL);
|
||||
|
||||
unlink(path);
|
||||
err = bpf_program__pin(prog, path);
|
||||
if (err) {
|
||||
fprintf(stderr, "Failed to pin program to %s: %s\n",
|
||||
path, strerror(-err));
|
||||
}
|
||||
|
||||
bpf_object__close(obj);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int qosify_loader_init(void)
|
||||
{
|
||||
static const struct {
|
||||
const char *suffix;
|
||||
uint32_t flags;
|
||||
} progs[] = {
|
||||
{ "egress_eth", 0 },
|
||||
{ "egress_ip", QOSIFY_IP_ONLY },
|
||||
{ "ingress_eth", QOSIFY_INGRESS },
|
||||
{ "ingress_ip", QOSIFY_INGRESS | QOSIFY_IP_ONLY },
|
||||
};
|
||||
glob_t g;
|
||||
int i;
|
||||
|
||||
if (glob(CLASSIFY_DATA_PATH "/*", 0, NULL, &g) == 0) {
|
||||
for (i = 0; i < g.gl_pathc; i++)
|
||||
unlink(g.gl_pathv[i]);
|
||||
}
|
||||
|
||||
|
||||
libbpf_set_print(qosify_bpf_pr);
|
||||
|
||||
qosify_init_env();
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(progs); i++) {
|
||||
if (qosify_create_program(progs[i].suffix, progs[i].flags))
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2021 Felix Fietkau <nbd@nbd.name>
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <libubox/uloop.h>
|
||||
|
||||
#include "qosify.h"
|
||||
|
||||
static int usage(const char *progname)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s [options]\n"
|
||||
"Options:\n"
|
||||
" -l <file> Load defaults from <file>\n"
|
||||
" -o only load program/maps without running as daemon\n"
|
||||
"\n", progname);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *load_file = NULL;
|
||||
bool oneshot = false;
|
||||
int ch;
|
||||
|
||||
while ((ch = getopt(argc, argv, "fl:o")) != -1) {
|
||||
switch (ch) {
|
||||
case 'f':
|
||||
break;
|
||||
case 'l':
|
||||
load_file = optarg;
|
||||
break;
|
||||
case 'o':
|
||||
oneshot = true;
|
||||
break;
|
||||
default:
|
||||
return usage(argv[0]);
|
||||
}
|
||||
}
|
||||
|
||||
if (qosify_loader_init())
|
||||
return 2;
|
||||
|
||||
if (qosify_map_init())
|
||||
return 2;
|
||||
|
||||
if (qosify_map_load_file(load_file))
|
||||
return 2;
|
||||
|
||||
if (oneshot)
|
||||
return 0;
|
||||
|
||||
ulog_open(ULOG_SYSLOG, LOG_DAEMON, "qosify");
|
||||
uloop_init();
|
||||
|
||||
if (qosify_ubus_init() ||
|
||||
qosify_iface_init())
|
||||
return 2;
|
||||
|
||||
uloop_run();
|
||||
|
||||
qosify_ubus_stop();
|
||||
qosify_iface_stop();
|
||||
|
||||
uloop_done();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,735 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2021 Felix Fietkau <nbd@nbd.name>
|
||||
*/
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <libubox/uloop.h>
|
||||
|
||||
#include "qosify.h"
|
||||
|
||||
static int qosify_map_entry_cmp(const void *k1, const void *k2, void *ptr);
|
||||
|
||||
static int qosify_map_fds[__CL_MAP_MAX];
|
||||
static AVL_TREE(map_data, qosify_map_entry_cmp, false, NULL);
|
||||
static LIST_HEAD(map_files);
|
||||
static uint32_t next_timeout;
|
||||
static uint8_t qosify_dscp_default[2] = { 0xff, 0xff };
|
||||
int qosify_map_timeout;
|
||||
int qosify_active_timeout;
|
||||
struct qosify_config config;
|
||||
|
||||
struct qosify_map_file {
|
||||
struct list_head list;
|
||||
char filename[];
|
||||
};
|
||||
|
||||
static const struct {
|
||||
const char *name;
|
||||
const char *type_name;
|
||||
} qosify_map_info[] = {
|
||||
[CL_MAP_TCP_PORTS] = { "tcp_ports", "tcp_port" },
|
||||
[CL_MAP_UDP_PORTS] = { "udp_ports", "udp_port" },
|
||||
[CL_MAP_IPV4_ADDR] = { "ipv4_map", "ipv4_addr" },
|
||||
[CL_MAP_IPV6_ADDR] = { "ipv6_map", "ipv6_addr" },
|
||||
[CL_MAP_CONFIG] = { "config", "config" },
|
||||
[CL_MAP_DNS] = { "dns", "dns" },
|
||||
};
|
||||
|
||||
static const struct {
|
||||
const char name[5];
|
||||
uint8_t val;
|
||||
} codepoints[] = {
|
||||
{ "CS0", 0 },
|
||||
{ "CS1", 8 },
|
||||
{ "CS2", 16 },
|
||||
{ "CS3", 24 },
|
||||
{ "CS4", 32 },
|
||||
{ "CS5", 40 },
|
||||
{ "CS6", 48 },
|
||||
{ "CS7", 56 },
|
||||
{ "AF11", 10 },
|
||||
{ "AF12", 12 },
|
||||
{ "AF13", 14 },
|
||||
{ "AF21", 18 },
|
||||
{ "AF22", 20 },
|
||||
{ "AF22", 22 },
|
||||
{ "AF31", 26 },
|
||||
{ "AF32", 28 },
|
||||
{ "AF33", 30 },
|
||||
{ "AF41", 34 },
|
||||
{ "AF42", 36 },
|
||||
{ "AF43", 38 },
|
||||
{ "EF", 46 },
|
||||
{ "VA", 44 },
|
||||
{ "LE", 1 },
|
||||
{ "DF", 0 },
|
||||
};
|
||||
|
||||
static void qosify_map_timer_cb(struct uloop_timeout *t)
|
||||
{
|
||||
qosify_map_gc();
|
||||
}
|
||||
|
||||
static struct uloop_timeout qosify_map_timer = {
|
||||
.cb = qosify_map_timer_cb,
|
||||
};
|
||||
|
||||
static uint32_t qosify_gettime(void)
|
||||
{
|
||||
struct timespec ts;
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
|
||||
return ts.tv_sec;
|
||||
}
|
||||
|
||||
static const char *
|
||||
qosify_map_path(enum qosify_map_id id)
|
||||
{
|
||||
static char path[128];
|
||||
const char *name;
|
||||
|
||||
if (id >= ARRAY_SIZE(qosify_map_info))
|
||||
return NULL;
|
||||
|
||||
name = qosify_map_info[id].name;
|
||||
if (!name)
|
||||
return NULL;
|
||||
|
||||
snprintf(path, sizeof(path), "%s/%s", CLASSIFY_DATA_PATH, name);
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
static int qosify_map_get_fd(enum qosify_map_id id)
|
||||
{
|
||||
const char *path = qosify_map_path(id);
|
||||
int fd;
|
||||
|
||||
if (!path)
|
||||
return -1;
|
||||
|
||||
fd = bpf_obj_get(path);
|
||||
if (fd < 0)
|
||||
fprintf(stderr, "Failed to open map %s: %s\n", path, strerror(errno));
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
static void qosify_map_clear_list(enum qosify_map_id id)
|
||||
{
|
||||
int fd = qosify_map_fds[id];
|
||||
__u32 key[4] = {};
|
||||
|
||||
while (bpf_map_get_next_key(fd, &key, &key) != -1)
|
||||
bpf_map_delete_elem(fd, &key);
|
||||
}
|
||||
|
||||
static void __qosify_map_set_dscp_default(enum qosify_map_id id, uint8_t val)
|
||||
{
|
||||
struct qosify_map_data data = {
|
||||
.id = id,
|
||||
};
|
||||
int fd = qosify_map_fds[id];
|
||||
int i;
|
||||
|
||||
val |= QOSIFY_DSCP_DEFAULT_FLAG;
|
||||
|
||||
for (i = 0; i < (1 << 16); i++) {
|
||||
data.addr.port = htons(i);
|
||||
if (avl_find(&map_data, &data))
|
||||
continue;
|
||||
|
||||
bpf_map_update_elem(fd, &data.addr, &val, BPF_ANY);
|
||||
}
|
||||
}
|
||||
|
||||
void qosify_map_set_dscp_default(enum qosify_map_id id, uint8_t val)
|
||||
{
|
||||
bool udp;
|
||||
|
||||
if (id == CL_MAP_TCP_PORTS)
|
||||
udp = false;
|
||||
else if (id == CL_MAP_UDP_PORTS)
|
||||
udp = true;
|
||||
else
|
||||
return;
|
||||
|
||||
if (qosify_dscp_default[udp] == val)
|
||||
return;
|
||||
|
||||
qosify_dscp_default[udp] = val;
|
||||
__qosify_map_set_dscp_default(id, val);
|
||||
}
|
||||
|
||||
int qosify_map_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < CL_MAP_DNS; i++) {
|
||||
qosify_map_fds[i] = qosify_map_get_fd(i);
|
||||
if (qosify_map_fds[i] < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
qosify_map_clear_list(CL_MAP_IPV4_ADDR);
|
||||
qosify_map_clear_list(CL_MAP_IPV6_ADDR);
|
||||
qosify_map_reset_config();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *str_skip(char *str, bool space)
|
||||
{
|
||||
while (*str && isspace(*str) == space)
|
||||
str++;
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
static int
|
||||
qosify_map_codepoint(const char *val)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(codepoints); i++)
|
||||
if (!strcmp(codepoints[i].name, val))
|
||||
return codepoints[i].val;
|
||||
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
static int qosify_map_entry_cmp(const void *k1, const void *k2, void *ptr)
|
||||
{
|
||||
const struct qosify_map_data *d1 = k1;
|
||||
const struct qosify_map_data *d2 = k2;
|
||||
|
||||
if (d1->id != d2->id)
|
||||
return d2->id - d1->id;
|
||||
|
||||
if (d1->id == CL_MAP_DNS)
|
||||
return strcmp(d1->addr.dns.pattern, d2->addr.dns.pattern);
|
||||
|
||||
return memcmp(&d1->addr, &d2->addr, sizeof(d1->addr));
|
||||
}
|
||||
|
||||
static struct qosify_map_entry *
|
||||
__qosify_map_alloc_entry(struct qosify_map_data *data)
|
||||
{
|
||||
struct qosify_map_entry *e;
|
||||
char *pattern;
|
||||
|
||||
if (data->id < CL_MAP_DNS) {
|
||||
e = calloc(1, sizeof(*e));
|
||||
memcpy(&e->data.addr, &data->addr, sizeof(e->data.addr));
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
e = calloc_a(sizeof(*e), &pattern, strlen(data->addr.dns.pattern) + 1);
|
||||
strcpy(pattern, data->addr.dns.pattern);
|
||||
e->data.addr.dns.pattern = pattern;
|
||||
if (regcomp(&e->data.addr.dns.regex, pattern,
|
||||
REG_EXTENDED | REG_ICASE | REG_NOSUB)) {
|
||||
free(e);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
static void __qosify_map_set_entry(struct qosify_map_data *data)
|
||||
{
|
||||
int fd = qosify_map_fds[data->id];
|
||||
struct qosify_map_entry *e;
|
||||
bool file = data->file;
|
||||
int32_t delta = 0;
|
||||
bool add = data->dscp != 0xff;
|
||||
uint8_t prev_dscp = 0xff;
|
||||
|
||||
e = avl_find_element(&map_data, data, e, avl);
|
||||
if (!e) {
|
||||
if (!add)
|
||||
return;
|
||||
|
||||
e = __qosify_map_alloc_entry(data);
|
||||
if (!e)
|
||||
return;
|
||||
|
||||
e->avl.key = &e->data;
|
||||
e->data.id = data->id;
|
||||
avl_insert(&map_data, &e->avl);
|
||||
} else {
|
||||
prev_dscp = e->data.dscp;
|
||||
}
|
||||
|
||||
if (file)
|
||||
e->data.file = add;
|
||||
else
|
||||
e->data.user = add;
|
||||
|
||||
if (add) {
|
||||
if (file)
|
||||
e->data.file_dscp = data->dscp;
|
||||
if (!e->data.user || !file)
|
||||
e->data.dscp = data->dscp;
|
||||
} else if (e->data.file && !file) {
|
||||
e->data.dscp = e->data.file_dscp;
|
||||
}
|
||||
|
||||
if (e->data.dscp != prev_dscp && data->id < CL_MAP_DNS) {
|
||||
struct qosify_ip_map_val val = {
|
||||
.dscp = e->data.dscp,
|
||||
.seen = 1,
|
||||
};
|
||||
|
||||
bpf_map_update_elem(fd, &data->addr, &val, BPF_ANY);
|
||||
}
|
||||
|
||||
if (add) {
|
||||
if (qosify_map_timeout == ~0 || file) {
|
||||
e->timeout = ~0;
|
||||
return;
|
||||
}
|
||||
|
||||
e->timeout = qosify_gettime() + qosify_map_timeout;
|
||||
delta = e->timeout - next_timeout;
|
||||
if (next_timeout && delta >= 0)
|
||||
return;
|
||||
}
|
||||
|
||||
uloop_timeout_set(&qosify_map_timer, 1);
|
||||
}
|
||||
|
||||
static int
|
||||
qosify_map_set_port(struct qosify_map_data *data, const char *str)
|
||||
{
|
||||
unsigned long start_port, end_port;
|
||||
char *err;
|
||||
int i;
|
||||
|
||||
start_port = end_port = strtoul(str, &err, 0);
|
||||
if (err && *err) {
|
||||
if (*err == '-')
|
||||
end_port = strtoul(err + 1, &err, 0);
|
||||
if (*err)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!start_port || end_port < start_port ||
|
||||
end_port >= 65535)
|
||||
return -1;
|
||||
|
||||
for (i = start_port; i <= end_port; i++) {
|
||||
data->addr.port = htons(i);
|
||||
__qosify_map_set_entry(data);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
qosify_map_fill_ip(struct qosify_map_data *data, const char *str)
|
||||
{
|
||||
int af;
|
||||
|
||||
if (data->id == CL_MAP_IPV6_ADDR)
|
||||
af = AF_INET6;
|
||||
else
|
||||
af = AF_INET;
|
||||
|
||||
if (inet_pton(af, str, &data->addr) != 1)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int qosify_map_set_entry(enum qosify_map_id id, bool file, const char *str, uint8_t dscp)
|
||||
{
|
||||
struct qosify_map_data data = {
|
||||
.id = id,
|
||||
.file = file,
|
||||
.dscp = dscp,
|
||||
};
|
||||
|
||||
switch (id) {
|
||||
case CL_MAP_DNS:
|
||||
data.addr.dns.pattern = str;
|
||||
break;
|
||||
case CL_MAP_TCP_PORTS:
|
||||
case CL_MAP_UDP_PORTS:
|
||||
return qosify_map_set_port(&data, str);
|
||||
case CL_MAP_IPV4_ADDR:
|
||||
case CL_MAP_IPV6_ADDR:
|
||||
if (qosify_map_fill_ip(&data, str))
|
||||
return -1;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
__qosify_map_set_entry(&data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int qosify_map_dscp_value(const char *val)
|
||||
{
|
||||
unsigned long dscp;
|
||||
char *err;
|
||||
bool fallback = false;
|
||||
|
||||
if (*val == '+') {
|
||||
fallback = true;
|
||||
val++;
|
||||
}
|
||||
|
||||
dscp = strtoul(val, &err, 0);
|
||||
if (err && *err)
|
||||
dscp = qosify_map_codepoint(val);
|
||||
|
||||
if (dscp >= 64)
|
||||
return -1;
|
||||
|
||||
return dscp + (fallback << 6);
|
||||
}
|
||||
|
||||
static void
|
||||
qosify_map_dscp_codepoint_str(char *dest, int len, uint8_t dscp)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (dscp & QOSIFY_DSCP_FALLBACK_FLAG) {
|
||||
*(dest++) = '+';
|
||||
len--;
|
||||
dscp &= ~QOSIFY_DSCP_FALLBACK_FLAG;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(codepoints); i++) {
|
||||
if (codepoints[i].val != dscp)
|
||||
continue;
|
||||
|
||||
snprintf(dest, len, "%s", codepoints[i].name);
|
||||
return;
|
||||
}
|
||||
|
||||
snprintf(dest, len, "0x%x", dscp);
|
||||
}
|
||||
|
||||
static void
|
||||
qosify_map_parse_line(char *str)
|
||||
{
|
||||
const char *key, *value;
|
||||
int dscp;
|
||||
|
||||
str = str_skip(str, true);
|
||||
key = str;
|
||||
|
||||
str = str_skip(str, false);
|
||||
if (!*str)
|
||||
return;
|
||||
|
||||
*(str++) = 0;
|
||||
str = str_skip(str, true);
|
||||
value = str;
|
||||
|
||||
dscp = qosify_map_dscp_value(value);
|
||||
if (dscp < 0)
|
||||
return;
|
||||
|
||||
if (!strncmp(key, "dns:", 4))
|
||||
qosify_map_set_entry(CL_MAP_DNS, true, key + 4, dscp);
|
||||
if (!strncmp(key, "tcp:", 4))
|
||||
qosify_map_set_entry(CL_MAP_TCP_PORTS, true, key + 4, dscp);
|
||||
else if (!strncmp(key, "udp:", 4))
|
||||
qosify_map_set_entry(CL_MAP_UDP_PORTS, true, key + 4, dscp);
|
||||
else if (strchr(key, ':'))
|
||||
qosify_map_set_entry(CL_MAP_IPV6_ADDR, true, key, dscp);
|
||||
else if (strchr(key, '.'))
|
||||
qosify_map_set_entry(CL_MAP_IPV4_ADDR, true, key, dscp);
|
||||
}
|
||||
|
||||
static int __qosify_map_load_file(const char *file)
|
||||
{
|
||||
char line[1024];
|
||||
char *cur;
|
||||
FILE *f;
|
||||
|
||||
if (!file)
|
||||
return 0;
|
||||
|
||||
f = fopen(file, "r");
|
||||
if (!f) {
|
||||
fprintf(stderr, "Can't open data file %s\n", file);
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (fgets(line, sizeof(line), f)) {
|
||||
cur = strchr(line, '#');
|
||||
if (cur)
|
||||
*cur = 0;
|
||||
|
||||
cur = line + strlen(line);
|
||||
if (cur == line)
|
||||
continue;
|
||||
|
||||
while (cur > line && isspace(cur[-1]))
|
||||
cur--;
|
||||
|
||||
*cur = 0;
|
||||
qosify_map_parse_line(line);
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int qosify_map_load_file(const char *file)
|
||||
{
|
||||
struct qosify_map_file *f;
|
||||
|
||||
if (!file)
|
||||
return 0;
|
||||
|
||||
f = calloc(1, sizeof(*f) + strlen(file) + 1);
|
||||
strcpy(f->filename, file);
|
||||
list_add_tail(&f->list, &map_files);
|
||||
|
||||
return __qosify_map_load_file(file);
|
||||
}
|
||||
|
||||
static void qosify_map_reset_file_entries(void)
|
||||
{
|
||||
struct qosify_map_entry *e;
|
||||
|
||||
avl_for_each_element(&map_data, e, avl)
|
||||
e->data.file = false;
|
||||
}
|
||||
|
||||
void qosify_map_clear_files(void)
|
||||
{
|
||||
struct qosify_map_file *f, *tmp;
|
||||
|
||||
qosify_map_reset_file_entries();
|
||||
|
||||
list_for_each_entry_safe(f, tmp, &map_files, list) {
|
||||
list_del(&f->list);
|
||||
free(f);
|
||||
}
|
||||
}
|
||||
|
||||
void qosify_map_reset_config(void)
|
||||
{
|
||||
qosify_map_clear_files();
|
||||
qosify_map_set_dscp_default(CL_MAP_TCP_PORTS, 0);
|
||||
qosify_map_set_dscp_default(CL_MAP_UDP_PORTS, 0);
|
||||
qosify_map_timeout = 3600;
|
||||
qosify_active_timeout = 300;
|
||||
|
||||
memset(&config, 0, sizeof(config));
|
||||
config.dscp_prio = 0xff;
|
||||
config.dscp_bulk = 0xff;
|
||||
config.dscp_icmp = 0xff;
|
||||
}
|
||||
|
||||
void qosify_map_reload(void)
|
||||
{
|
||||
struct qosify_map_file *f;
|
||||
|
||||
qosify_map_reset_file_entries();
|
||||
|
||||
list_for_each_entry(f, &map_files, list)
|
||||
__qosify_map_load_file(f->filename);
|
||||
|
||||
qosify_map_gc();
|
||||
}
|
||||
|
||||
static void qosify_map_free_entry(struct qosify_map_entry *e)
|
||||
{
|
||||
int fd = qosify_map_fds[e->data.id];
|
||||
|
||||
avl_delete(&map_data, &e->avl);
|
||||
if (e->data.id < CL_MAP_DNS)
|
||||
bpf_map_delete_elem(fd, &e->data.addr);
|
||||
free(e);
|
||||
}
|
||||
|
||||
static bool
|
||||
qosify_map_entry_refresh_timeout(struct qosify_map_entry *e)
|
||||
{
|
||||
struct qosify_ip_map_val val;
|
||||
int fd = qosify_map_fds[e->data.id];
|
||||
|
||||
if (e->data.id != CL_MAP_IPV4_ADDR &&
|
||||
e->data.id != CL_MAP_IPV6_ADDR)
|
||||
return false;
|
||||
|
||||
if (bpf_map_lookup_elem(fd, &e->data.addr, &val))
|
||||
return false;
|
||||
|
||||
if (!val.seen)
|
||||
return false;
|
||||
|
||||
e->timeout = qosify_gettime() + qosify_active_timeout;
|
||||
val.seen = 0;
|
||||
bpf_map_update_elem(fd, &e->data.addr, &val, BPF_ANY);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void qosify_map_gc(void)
|
||||
{
|
||||
struct qosify_map_entry *e, *tmp;
|
||||
int32_t timeout = 0;
|
||||
uint32_t cur_time = qosify_gettime();
|
||||
|
||||
next_timeout = 0;
|
||||
avl_for_each_element_safe(&map_data, e, avl, tmp) {
|
||||
int32_t cur_timeout;
|
||||
|
||||
if (e->data.user && e->timeout != ~0) {
|
||||
cur_timeout = e->timeout - cur_time;
|
||||
if (cur_timeout <= 0 &&
|
||||
qosify_map_entry_refresh_timeout(e))
|
||||
cur_timeout = e->timeout - cur_time;
|
||||
if (cur_timeout <= 0) {
|
||||
e->data.user = false;
|
||||
e->data.dscp = e->data.file_dscp;
|
||||
} else if (!timeout || cur_timeout < timeout) {
|
||||
timeout = cur_timeout;
|
||||
next_timeout = e->timeout;
|
||||
}
|
||||
}
|
||||
|
||||
if (e->data.file || e->data.user)
|
||||
continue;
|
||||
|
||||
qosify_map_free_entry(e);
|
||||
}
|
||||
|
||||
if (!timeout)
|
||||
return;
|
||||
|
||||
uloop_timeout_set(&qosify_map_timer, timeout * 1000);
|
||||
}
|
||||
|
||||
|
||||
int qosify_map_add_dns_host(const char *host, const char *addr, const char *type, int ttl)
|
||||
{
|
||||
struct qosify_map_data data = {
|
||||
.id = CL_MAP_DNS,
|
||||
.addr.dns.pattern = "",
|
||||
};
|
||||
struct qosify_map_entry *e;
|
||||
int prev_timeout = qosify_map_timeout;
|
||||
|
||||
e = avl_find_ge_element(&map_data, &data, e, avl);
|
||||
if (!e)
|
||||
return 0;
|
||||
|
||||
memset(&data, 0, sizeof(data));
|
||||
data.user = true;
|
||||
if (!strcmp(type, "A"))
|
||||
data.id = CL_MAP_IPV4_ADDR;
|
||||
else if (!strcmp(type, "AAAA"))
|
||||
data.id = CL_MAP_IPV6_ADDR;
|
||||
else
|
||||
return 0;
|
||||
|
||||
if (qosify_map_fill_ip(&data, addr))
|
||||
return -1;
|
||||
|
||||
avl_for_element_to_last(&map_data, e, e, avl) {
|
||||
regex_t *regex = &e->data.addr.dns.regex;
|
||||
|
||||
if (e->data.id != CL_MAP_DNS)
|
||||
return 0;
|
||||
|
||||
if (regexec(regex, host, 0, NULL, 0) != 0)
|
||||
continue;
|
||||
|
||||
if (ttl)
|
||||
qosify_map_timeout = ttl;
|
||||
data.dscp = e->data.dscp;
|
||||
__qosify_map_set_entry(&data);
|
||||
qosify_map_timeout = prev_timeout;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void qosify_map_dump(struct blob_buf *b)
|
||||
{
|
||||
struct qosify_map_entry *e;
|
||||
uint32_t cur_time = qosify_gettime();
|
||||
int buf_len = INET6_ADDRSTRLEN + 1;
|
||||
char *buf;
|
||||
void *a;
|
||||
int af;
|
||||
|
||||
a = blobmsg_open_array(b, "entries");
|
||||
avl_for_each_element(&map_data, e, avl) {
|
||||
void *c;
|
||||
|
||||
if (!e->data.file && !e->data.user)
|
||||
continue;
|
||||
|
||||
c = blobmsg_open_table(b, NULL);
|
||||
if (e->data.user && e->timeout != ~0) {
|
||||
int32_t cur_timeout = e->timeout - cur_time;
|
||||
|
||||
if (cur_timeout < 0)
|
||||
cur_timeout = 0;
|
||||
|
||||
blobmsg_add_u32(b, "timeout", cur_timeout);
|
||||
}
|
||||
|
||||
blobmsg_add_u8(b, "file", e->data.file);
|
||||
blobmsg_add_u8(b, "user", e->data.user);
|
||||
|
||||
buf = blobmsg_alloc_string_buffer(b, "dscp", buf_len);
|
||||
qosify_map_dscp_codepoint_str(buf, buf_len, e->data.dscp);
|
||||
blobmsg_add_string_buffer(b);
|
||||
|
||||
blobmsg_add_string(b, "type", qosify_map_info[e->data.id].type_name);
|
||||
|
||||
switch (e->data.id) {
|
||||
case CL_MAP_TCP_PORTS:
|
||||
case CL_MAP_UDP_PORTS:
|
||||
blobmsg_printf(b, "addr", "%d", ntohs(e->data.addr.port));
|
||||
break;
|
||||
case CL_MAP_IPV4_ADDR:
|
||||
case CL_MAP_IPV6_ADDR:
|
||||
buf = blobmsg_alloc_string_buffer(b, "addr", buf_len);
|
||||
af = e->data.id == CL_MAP_IPV6_ADDR ? AF_INET6 : AF_INET;
|
||||
inet_ntop(af, &e->data.addr, buf, buf_len);
|
||||
blobmsg_add_string_buffer(b);
|
||||
break;
|
||||
case CL_MAP_DNS:
|
||||
blobmsg_add_string(b, "addr", e->data.addr.dns.pattern);
|
||||
break;
|
||||
default:
|
||||
*buf = 0;
|
||||
break;
|
||||
}
|
||||
blobmsg_close_table(b, c);
|
||||
}
|
||||
blobmsg_close_array(b, a);
|
||||
}
|
||||
|
||||
void qosify_map_update_config(void)
|
||||
{
|
||||
int fd = qosify_map_fds[CL_MAP_CONFIG];
|
||||
uint32_t key = 0;
|
||||
|
||||
bpf_map_update_elem(fd, &key, &config, BPF_ANY);
|
||||
}
|
||||
@@ -1,464 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2021 Felix Fietkau <nbd@nbd.name>
|
||||
*/
|
||||
#define KBUILD_MODNAME "foo"
|
||||
#include <uapi/linux/bpf.h>
|
||||
#include <uapi/linux/if_ether.h>
|
||||
#include <uapi/linux/if_packet.h>
|
||||
#include <uapi/linux/ip.h>
|
||||
#include <uapi/linux/ipv6.h>
|
||||
#include <uapi/linux/in.h>
|
||||
#include <uapi/linux/tcp.h>
|
||||
#include <uapi/linux/udp.h>
|
||||
#include <uapi/linux/filter.h>
|
||||
#include <uapi/linux/pkt_cls.h>
|
||||
#include <linux/ip.h>
|
||||
#include <net/ipv6.h>
|
||||
#include <bpf/bpf_helpers.h>
|
||||
#include <bpf/bpf_endian.h>
|
||||
#include "qosify-bpf.h"
|
||||
|
||||
#define INET_ECN_MASK 3
|
||||
|
||||
#define FLOW_CHECK_INTERVAL ((u32)((1000000000ULL) >> 24))
|
||||
#define FLOW_TIMEOUT ((u32)((30ULL * 1000000000ULL) >> 24))
|
||||
#define FLOW_BULK_TIMEOUT 5
|
||||
|
||||
#define EWMA_SHIFT 12
|
||||
|
||||
const volatile static uint32_t module_flags = 0;
|
||||
|
||||
struct flow_bucket {
|
||||
__u32 last_update;
|
||||
__u32 pkt_len_avg;
|
||||
__u16 pkt_count;
|
||||
__u8 dscp;
|
||||
__u8 bulk_timeout;
|
||||
};
|
||||
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_ARRAY);
|
||||
__uint(pinning, 1);
|
||||
__type(key, __u32);
|
||||
__type(value, struct qosify_config);
|
||||
__uint(max_entries, 1);
|
||||
} config SEC(".maps");
|
||||
|
||||
typedef struct {
|
||||
__uint(type, BPF_MAP_TYPE_ARRAY);
|
||||
__uint(pinning, 1);
|
||||
__type(key, __u32);
|
||||
__type(value, __u8);
|
||||
__uint(max_entries, 1 << 16);
|
||||
} port_array_t;
|
||||
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_LRU_HASH);
|
||||
__uint(pinning, 1);
|
||||
__type(key, __u32);
|
||||
__uint(value_size, sizeof(struct flow_bucket));
|
||||
__uint(max_entries, QOSIFY_FLOW_BUCKETS);
|
||||
} flow_map SEC(".maps");
|
||||
|
||||
port_array_t tcp_ports SEC(".maps");
|
||||
port_array_t udp_ports SEC(".maps");
|
||||
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_HASH);
|
||||
__uint(pinning, 1);
|
||||
__uint(key_size, sizeof(struct in_addr));
|
||||
__type(value, struct qosify_ip_map_val);
|
||||
__uint(max_entries, 100000);
|
||||
__uint(map_flags, BPF_F_NO_PREALLOC);
|
||||
} ipv4_map SEC(".maps");
|
||||
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_HASH);
|
||||
__uint(pinning, 1);
|
||||
__uint(key_size, sizeof(struct in6_addr));
|
||||
__type(value, struct qosify_ip_map_val);
|
||||
__uint(max_entries, 100000);
|
||||
__uint(map_flags, BPF_F_NO_PREALLOC);
|
||||
} ipv6_map SEC(".maps");
|
||||
|
||||
static struct qosify_config *get_config(void)
|
||||
{
|
||||
__u32 key = 0;
|
||||
|
||||
return bpf_map_lookup_elem(&config, &key);
|
||||
}
|
||||
|
||||
static __always_inline int proto_is_vlan(__u16 h_proto)
|
||||
{
|
||||
return !!(h_proto == bpf_htons(ETH_P_8021Q) ||
|
||||
h_proto == bpf_htons(ETH_P_8021AD));
|
||||
}
|
||||
|
||||
static __always_inline int proto_is_ip(__u16 h_proto)
|
||||
{
|
||||
return !!(h_proto == bpf_htons(ETH_P_IP) ||
|
||||
h_proto == bpf_htons(ETH_P_IPV6));
|
||||
}
|
||||
|
||||
static __always_inline void *skb_ptr(struct __sk_buff *skb, __u32 offset)
|
||||
{
|
||||
void *start = (void *)(unsigned long long)skb->data;
|
||||
|
||||
return start + offset;
|
||||
}
|
||||
|
||||
static __always_inline void *skb_end_ptr(struct __sk_buff *skb)
|
||||
{
|
||||
return (void *)(unsigned long long)skb->data_end;
|
||||
}
|
||||
|
||||
static __always_inline int skb_check(struct __sk_buff *skb, void *ptr)
|
||||
{
|
||||
if (ptr > skb_end_ptr(skb))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __always_inline __u32 cur_time(void)
|
||||
{
|
||||
__u32 val = bpf_ktime_get_ns() >> 24;
|
||||
|
||||
if (!val)
|
||||
val = 1;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static __always_inline __u32 ewma(__u32 *avg, __u32 val)
|
||||
{
|
||||
if (*avg)
|
||||
*avg = (*avg * 3) / 4 + (val << EWMA_SHIFT) / 4;
|
||||
else
|
||||
*avg = val << EWMA_SHIFT;
|
||||
|
||||
return *avg >> EWMA_SHIFT;
|
||||
}
|
||||
|
||||
static __always_inline void
|
||||
ipv4_change_dsfield(struct iphdr *iph, __u8 mask, __u8 value, bool force)
|
||||
{
|
||||
__u32 check = bpf_ntohs(iph->check);
|
||||
__u8 dsfield;
|
||||
|
||||
if ((iph->tos & mask) && !force)
|
||||
return;
|
||||
|
||||
dsfield = (iph->tos & mask) | value;
|
||||
if (iph->tos == dsfield)
|
||||
return;
|
||||
|
||||
check += iph->tos;
|
||||
if ((check + 1) >> 16)
|
||||
check = (check + 1) & 0xffff;
|
||||
check -= dsfield;
|
||||
check += check >> 16;
|
||||
iph->check = bpf_htons(check);
|
||||
iph->tos = dsfield;
|
||||
}
|
||||
|
||||
static __always_inline void
|
||||
ipv6_change_dsfield(struct ipv6hdr *ipv6h, __u8 mask, __u8 value, bool force)
|
||||
{
|
||||
__u16 *p = (__u16 *)ipv6h;
|
||||
__u16 val;
|
||||
|
||||
if (((*p >> 4) & mask) && !force)
|
||||
return;
|
||||
|
||||
val = (*p & bpf_htons((((__u16)mask << 4) | 0xf00f))) | bpf_htons((__u16)value << 4);
|
||||
if (val == *p)
|
||||
return;
|
||||
|
||||
*p = val;
|
||||
}
|
||||
|
||||
static __always_inline int
|
||||
parse_ethernet(struct __sk_buff *skb, __u32 *offset)
|
||||
{
|
||||
struct ethhdr *eth;
|
||||
__u16 h_proto;
|
||||
int i;
|
||||
|
||||
eth = skb_ptr(skb, *offset);
|
||||
if (skb_check(skb, eth + 1))
|
||||
return -1;
|
||||
|
||||
h_proto = eth->h_proto;
|
||||
*offset += sizeof(*eth);
|
||||
|
||||
#pragma unroll
|
||||
for (i = 0; i < 2; i++) {
|
||||
struct vlan_hdr *vlh = skb_ptr(skb, *offset);
|
||||
|
||||
if (!proto_is_vlan(h_proto))
|
||||
break;
|
||||
|
||||
if (skb_check(skb, vlh + 1))
|
||||
return -1;
|
||||
|
||||
h_proto = vlh->h_vlan_encapsulated_proto;
|
||||
*offset += sizeof(*vlh);
|
||||
}
|
||||
|
||||
return h_proto;
|
||||
}
|
||||
|
||||
static void
|
||||
parse_l4proto(struct qosify_config *config, struct __sk_buff *skb,
|
||||
__u32 offset, __u8 proto, __u8 *dscp_out)
|
||||
{
|
||||
struct udphdr *udp;
|
||||
__u32 src, dest, key;
|
||||
__u8 *value;
|
||||
|
||||
udp = skb_ptr(skb, offset);
|
||||
if (skb_check(skb, &udp->len))
|
||||
return;
|
||||
|
||||
if (config && (proto == IPPROTO_ICMP || proto == IPPROTO_ICMPV6)) {
|
||||
*dscp_out = config->dscp_icmp;
|
||||
return;
|
||||
}
|
||||
|
||||
src = udp->source;
|
||||
dest = udp->dest;
|
||||
|
||||
if (module_flags & QOSIFY_INGRESS)
|
||||
key = src;
|
||||
else
|
||||
key = dest;
|
||||
|
||||
if (proto == IPPROTO_TCP) {
|
||||
value = bpf_map_lookup_elem(&tcp_ports, &key);
|
||||
} else {
|
||||
if (proto != IPPROTO_UDP)
|
||||
key = 0;
|
||||
|
||||
value = bpf_map_lookup_elem(&udp_ports, &key);
|
||||
}
|
||||
|
||||
if (!value)
|
||||
return;
|
||||
|
||||
*dscp_out = *value;
|
||||
}
|
||||
|
||||
static void
|
||||
check_flow(struct qosify_config *config, struct __sk_buff *skb,
|
||||
uint8_t *dscp)
|
||||
{
|
||||
struct flow_bucket flow_data;
|
||||
struct flow_bucket *flow;
|
||||
__s32 delta;
|
||||
__u32 hash;
|
||||
__u32 time;
|
||||
|
||||
if (!(*dscp & QOSIFY_DSCP_DEFAULT_FLAG))
|
||||
return;
|
||||
|
||||
if (!config)
|
||||
return;
|
||||
|
||||
if (!config->bulk_trigger_pps &&
|
||||
!config->prio_max_avg_pkt_len)
|
||||
return;
|
||||
|
||||
time = cur_time();
|
||||
hash = bpf_get_hash_recalc(skb);
|
||||
flow = bpf_map_lookup_elem(&flow_map, &hash);
|
||||
if (!flow) {
|
||||
memset(&flow_data, 0, sizeof(flow_data));
|
||||
bpf_map_update_elem(&flow_map, &hash, &flow_data, BPF_ANY);
|
||||
flow = bpf_map_lookup_elem(&flow_map, &hash);
|
||||
if (!flow)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!flow->last_update)
|
||||
goto reset;
|
||||
|
||||
delta = time - flow->last_update;
|
||||
if ((u32)delta > FLOW_TIMEOUT)
|
||||
goto reset;
|
||||
|
||||
if (delta >= FLOW_CHECK_INTERVAL) {
|
||||
if (flow->bulk_timeout) {
|
||||
flow->bulk_timeout--;
|
||||
if (!flow->bulk_timeout)
|
||||
flow->dscp = 0xff;
|
||||
}
|
||||
|
||||
goto clear;
|
||||
}
|
||||
|
||||
if (flow->pkt_count < 0xffff)
|
||||
flow->pkt_count++;
|
||||
|
||||
if (config->bulk_trigger_pps &&
|
||||
flow->pkt_count > config->bulk_trigger_pps) {
|
||||
flow->dscp = config->dscp_bulk;
|
||||
flow->bulk_timeout = config->bulk_trigger_timeout;
|
||||
}
|
||||
|
||||
out:
|
||||
if (config->prio_max_avg_pkt_len &&
|
||||
flow->dscp != config->dscp_bulk) {
|
||||
if (ewma(&flow->pkt_len_avg, skb->len) <
|
||||
config->prio_max_avg_pkt_len)
|
||||
flow->dscp = config->dscp_prio;
|
||||
else
|
||||
flow->dscp = 0xff;
|
||||
}
|
||||
|
||||
if (flow->dscp != 0xff)
|
||||
*dscp = flow->dscp;
|
||||
|
||||
return;
|
||||
|
||||
reset:
|
||||
flow->dscp = 0xff;
|
||||
flow->pkt_len_avg = 0;
|
||||
clear:
|
||||
flow->pkt_count = 1;
|
||||
flow->last_update = time;
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
static __always_inline void
|
||||
parse_ipv4(struct __sk_buff *skb, __u32 *offset)
|
||||
{
|
||||
struct qosify_config *config;
|
||||
struct qosify_ip_map_val *ip_val;
|
||||
const __u32 zero_port = 0;
|
||||
struct iphdr *iph;
|
||||
__u8 dscp = 0xff;
|
||||
__u8 *value;
|
||||
__u8 ipproto;
|
||||
int hdr_len;
|
||||
void *key;
|
||||
bool force;
|
||||
|
||||
config = get_config();
|
||||
|
||||
iph = skb_ptr(skb, *offset);
|
||||
if (skb_check(skb, iph + 1))
|
||||
return;
|
||||
|
||||
hdr_len = iph->ihl * 4;
|
||||
if (bpf_skb_pull_data(skb, *offset + hdr_len + sizeof(struct udphdr)))
|
||||
return;
|
||||
|
||||
iph = skb_ptr(skb, *offset);
|
||||
*offset += hdr_len;
|
||||
|
||||
if (skb_check(skb, (void *)(iph + 1)))
|
||||
return;
|
||||
|
||||
ipproto = iph->protocol;
|
||||
parse_l4proto(config, skb, *offset, ipproto, &dscp);
|
||||
|
||||
if (module_flags & QOSIFY_INGRESS)
|
||||
key = &iph->saddr;
|
||||
else
|
||||
key = &iph->daddr;
|
||||
|
||||
ip_val = bpf_map_lookup_elem(&ipv4_map, key);
|
||||
if (ip_val) {
|
||||
if (!ip_val->seen)
|
||||
ip_val->seen = 1;
|
||||
dscp = ip_val->dscp;
|
||||
} else if (dscp == 0xff) {
|
||||
/* use udp port 0 entry as fallback for non-tcp/udp */
|
||||
value = bpf_map_lookup_elem(&udp_ports, &zero_port);
|
||||
if (value)
|
||||
dscp = *value;
|
||||
}
|
||||
|
||||
check_flow(config, skb, &dscp);
|
||||
|
||||
force = !(dscp & QOSIFY_DSCP_FALLBACK_FLAG);
|
||||
dscp &= GENMASK(5, 0);
|
||||
|
||||
ipv4_change_dsfield(iph, INET_ECN_MASK, dscp << 2, force);
|
||||
}
|
||||
|
||||
static __always_inline void
|
||||
parse_ipv6(struct __sk_buff *skb, __u32 *offset)
|
||||
{
|
||||
struct qosify_config *config;
|
||||
struct qosify_ip_map_val *ip_val;
|
||||
const __u32 zero_port = 0;
|
||||
struct ipv6hdr *iph;
|
||||
__u8 dscp = 0;
|
||||
__u8 *value;
|
||||
__u8 ipproto;
|
||||
void *key;
|
||||
bool force;
|
||||
|
||||
config = get_config();
|
||||
|
||||
if (bpf_skb_pull_data(skb, *offset + sizeof(*iph) + sizeof(struct udphdr)))
|
||||
return;
|
||||
|
||||
iph = skb_ptr(skb, *offset);
|
||||
*offset += sizeof(*iph);
|
||||
|
||||
if (skb_check(skb, (void *)(iph + 1)))
|
||||
return;
|
||||
|
||||
ipproto = iph->nexthdr;
|
||||
if (module_flags & QOSIFY_INGRESS)
|
||||
key = &iph->saddr;
|
||||
else
|
||||
key = &iph->daddr;
|
||||
|
||||
parse_l4proto(config, skb, *offset, ipproto, &dscp);
|
||||
|
||||
ip_val = bpf_map_lookup_elem(&ipv6_map, key);
|
||||
if (ip_val) {
|
||||
if (!ip_val->seen)
|
||||
ip_val->seen = 1;
|
||||
dscp = ip_val->dscp;
|
||||
} else if (dscp == 0xff) {
|
||||
/* use udp port 0 entry as fallback for non-tcp/udp */
|
||||
value = bpf_map_lookup_elem(&udp_ports, &zero_port);
|
||||
if (value)
|
||||
dscp = *value;
|
||||
}
|
||||
|
||||
check_flow(config, skb, &dscp);
|
||||
|
||||
force = !(dscp & QOSIFY_DSCP_FALLBACK_FLAG);
|
||||
dscp &= GENMASK(5, 0);
|
||||
|
||||
ipv6_change_dsfield(iph, INET_ECN_MASK, dscp << 2, force);
|
||||
}
|
||||
|
||||
SEC("classifier")
|
||||
int classify(struct __sk_buff *skb)
|
||||
{
|
||||
__u32 offset = 0;
|
||||
int type;
|
||||
|
||||
if (module_flags & QOSIFY_IP_ONLY)
|
||||
type = skb->protocol;
|
||||
else
|
||||
type = parse_ethernet(skb, &offset);
|
||||
|
||||
if (type == bpf_htons(ETH_P_IP))
|
||||
parse_ipv4(skb, &offset);
|
||||
else if (type == bpf_htons(ETH_P_IPV6))
|
||||
parse_ipv6(skb, &offset);
|
||||
|
||||
return TC_ACT_OK;
|
||||
}
|
||||
|
||||
char _license[] SEC("license") = "GPL";
|
||||
@@ -1,39 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2021 Felix Fietkau <nbd@nbd.name>
|
||||
*/
|
||||
#ifndef __BPF_QOSIFY_H
|
||||
#define __BPF_QOSIFY_H
|
||||
|
||||
#ifndef QOSIFY_FLOW_BUCKET_SHIFT
|
||||
#define QOSIFY_FLOW_BUCKET_SHIFT 13
|
||||
#endif
|
||||
|
||||
#define QOSIFY_FLOW_BUCKETS (1 << QOSIFY_FLOW_BUCKET_SHIFT)
|
||||
|
||||
/* rodata per-instance flags */
|
||||
#define QOSIFY_INGRESS (1 << 0)
|
||||
#define QOSIFY_IP_ONLY (1 << 1)
|
||||
|
||||
|
||||
#define QOSIFY_DSCP_FALLBACK_FLAG (1 << 6)
|
||||
#define QOSIFY_DSCP_DEFAULT_FLAG (1 << 7)
|
||||
|
||||
/* global config data */
|
||||
struct qosify_config {
|
||||
uint8_t dscp_prio;
|
||||
uint8_t dscp_bulk;
|
||||
uint8_t dscp_icmp;
|
||||
|
||||
uint8_t bulk_trigger_timeout;
|
||||
uint16_t bulk_trigger_pps;
|
||||
|
||||
uint16_t prio_max_avg_pkt_len;
|
||||
};
|
||||
|
||||
struct qosify_ip_map_val {
|
||||
uint8_t dscp; /* must be first */
|
||||
uint8_t seen;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,95 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2021 Felix Fietkau <nbd@nbd.name>
|
||||
*/
|
||||
#ifndef __QOS_CLASSIFY_H
|
||||
#define __QOS_CLASSIFY_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <regex.h>
|
||||
|
||||
#include <bpf/bpf.h>
|
||||
#include <bpf/libbpf.h>
|
||||
|
||||
#include "qosify-bpf.h"
|
||||
|
||||
#include <libubox/utils.h>
|
||||
#include <libubox/avl.h>
|
||||
#include <libubox/blobmsg.h>
|
||||
#include <libubox/ulog.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
|
||||
#define CLASSIFY_PROG_PATH "/lib/bpf/qosify-bpf.o"
|
||||
#define CLASSIFY_PIN_PATH "/sys/fs/bpf/qosify"
|
||||
#define CLASSIFY_DATA_PATH "/sys/fs/bpf/qosify_data"
|
||||
|
||||
enum qosify_map_id {
|
||||
CL_MAP_TCP_PORTS,
|
||||
CL_MAP_UDP_PORTS,
|
||||
CL_MAP_IPV4_ADDR,
|
||||
CL_MAP_IPV6_ADDR,
|
||||
CL_MAP_CONFIG,
|
||||
CL_MAP_DNS,
|
||||
__CL_MAP_MAX,
|
||||
};
|
||||
|
||||
struct qosify_map_data {
|
||||
enum qosify_map_id id;
|
||||
|
||||
bool file : 1;
|
||||
bool user : 1;
|
||||
|
||||
uint8_t dscp;
|
||||
uint8_t file_dscp;
|
||||
|
||||
union {
|
||||
uint32_t port;
|
||||
struct in_addr ip;
|
||||
struct in6_addr ip6;
|
||||
struct {
|
||||
const char *pattern;
|
||||
regex_t regex;
|
||||
} dns;
|
||||
} addr;
|
||||
};
|
||||
|
||||
struct qosify_map_entry {
|
||||
struct avl_node avl;
|
||||
|
||||
uint32_t timeout;
|
||||
|
||||
struct qosify_map_data data;
|
||||
};
|
||||
|
||||
|
||||
extern int qosify_map_timeout;
|
||||
extern int qosify_active_timeout;
|
||||
extern struct qosify_config config;
|
||||
|
||||
int qosify_loader_init(void);
|
||||
|
||||
int qosify_map_init(void);
|
||||
int qosify_map_dscp_value(const char *val);
|
||||
int qosify_map_load_file(const char *file);
|
||||
int qosify_map_set_entry(enum qosify_map_id id, bool file, const char *str, uint8_t dscp);
|
||||
void qosify_map_reload(void);
|
||||
void qosify_map_clear_files(void);
|
||||
void qosify_map_gc(void);
|
||||
void qosify_map_dump(struct blob_buf *b);
|
||||
void qosify_map_set_dscp_default(enum qosify_map_id id, uint8_t val);
|
||||
void qosify_map_reset_config(void);
|
||||
void qosify_map_update_config(void);
|
||||
int qosify_map_add_dns_host(const char *host, const char *addr, const char *type, int ttl);
|
||||
|
||||
int qosify_iface_init(void);
|
||||
void qosify_iface_config_update(struct blob_attr *ifaces, struct blob_attr *devs);
|
||||
void qosify_iface_check(void);
|
||||
void qosify_iface_status(struct blob_buf *b);
|
||||
void qosify_iface_stop(void);
|
||||
|
||||
int qosify_ubus_init(void);
|
||||
void qosify_ubus_stop(void);
|
||||
int qosify_ubus_check_interface(const char *name, char *ifname, int ifname_len);
|
||||
|
||||
#endif
|
||||
@@ -1,416 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2021 Felix Fietkau <nbd@nbd.name>
|
||||
*/
|
||||
#include <libubus.h>
|
||||
|
||||
#include "qosify.h"
|
||||
|
||||
static struct blob_buf b;
|
||||
|
||||
static int
|
||||
qosify_ubus_add_array(struct blob_attr *attr, uint8_t val, enum qosify_map_id id)
|
||||
{
|
||||
struct blob_attr *cur;
|
||||
int rem;
|
||||
|
||||
if (blobmsg_check_array(attr, BLOBMSG_TYPE_STRING) < 0)
|
||||
return UBUS_STATUS_INVALID_ARGUMENT;
|
||||
|
||||
blobmsg_for_each_attr(cur, attr, rem)
|
||||
qosify_map_set_entry(id, false, blobmsg_get_string(cur), val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
qosify_ubus_set_files(struct blob_attr *attr)
|
||||
{
|
||||
struct blob_attr *cur;
|
||||
int rem;
|
||||
|
||||
if (blobmsg_check_array(attr, BLOBMSG_TYPE_STRING) < 0)
|
||||
return UBUS_STATUS_INVALID_ARGUMENT;
|
||||
|
||||
qosify_map_clear_files();
|
||||
|
||||
blobmsg_for_each_attr(cur, attr, rem)
|
||||
qosify_map_load_file(blobmsg_get_string(cur));
|
||||
|
||||
qosify_map_gc();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
enum {
|
||||
CL_ADD_DSCP,
|
||||
CL_ADD_TIMEOUT,
|
||||
CL_ADD_IPV4,
|
||||
CL_ADD_IPV6,
|
||||
CL_ADD_TCP_PORT,
|
||||
CL_ADD_UDP_PORT,
|
||||
CL_ADD_DNS,
|
||||
__CL_ADD_MAX
|
||||
};
|
||||
|
||||
static const struct blobmsg_policy qosify_add_policy[__CL_ADD_MAX] = {
|
||||
[CL_ADD_DSCP] = { "dscp", BLOBMSG_TYPE_STRING },
|
||||
[CL_ADD_TIMEOUT] = { "timeout", BLOBMSG_TYPE_INT32 },
|
||||
[CL_ADD_IPV4] = { "ipv4", BLOBMSG_TYPE_ARRAY },
|
||||
[CL_ADD_IPV6] = { "ipv6", BLOBMSG_TYPE_ARRAY },
|
||||
[CL_ADD_TCP_PORT] = { "tcp_port", BLOBMSG_TYPE_ARRAY },
|
||||
[CL_ADD_UDP_PORT] = { "udp_port", BLOBMSG_TYPE_ARRAY },
|
||||
[CL_ADD_DNS] = { "dns", BLOBMSG_TYPE_ARRAY },
|
||||
};
|
||||
|
||||
|
||||
static int
|
||||
qosify_ubus_reload(struct ubus_context *ctx, struct ubus_object *obj,
|
||||
struct ubus_request_data *req, const char *method,
|
||||
struct blob_attr *msg)
|
||||
{
|
||||
qosify_map_reload();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
qosify_ubus_add(struct ubus_context *ctx, struct ubus_object *obj,
|
||||
struct ubus_request_data *req, const char *method,
|
||||
struct blob_attr *msg)
|
||||
{
|
||||
int prev_timemout = qosify_map_timeout;
|
||||
struct blob_attr *tb[__CL_ADD_MAX];
|
||||
struct blob_attr *cur;
|
||||
int dscp = -1;
|
||||
int ret;
|
||||
|
||||
blobmsg_parse(qosify_add_policy, __CL_ADD_MAX, tb,
|
||||
blobmsg_data(msg), blobmsg_len(msg));
|
||||
|
||||
if (!strcmp(method, "add")) {
|
||||
if ((cur = tb[CL_ADD_DSCP]) != NULL)
|
||||
dscp = qosify_map_dscp_value(blobmsg_get_string(cur));
|
||||
else
|
||||
return UBUS_STATUS_INVALID_ARGUMENT;
|
||||
if (dscp < 0)
|
||||
return UBUS_STATUS_INVALID_ARGUMENT;
|
||||
|
||||
if ((cur = tb[CL_ADD_TIMEOUT]) != NULL)
|
||||
qosify_map_timeout = blobmsg_get_u32(cur);
|
||||
} else {
|
||||
dscp = 0xff;
|
||||
}
|
||||
|
||||
if ((cur = tb[CL_ADD_IPV4]) != NULL &&
|
||||
(ret = qosify_ubus_add_array(cur, dscp, CL_MAP_IPV4_ADDR) != 0))
|
||||
return ret;
|
||||
|
||||
if ((cur = tb[CL_ADD_IPV6]) != NULL &&
|
||||
(ret = qosify_ubus_add_array(cur, dscp, CL_MAP_IPV6_ADDR) != 0))
|
||||
return ret;
|
||||
|
||||
if ((cur = tb[CL_ADD_TCP_PORT]) != NULL &&
|
||||
(ret = qosify_ubus_add_array(cur, dscp, CL_MAP_TCP_PORTS) != 0))
|
||||
return ret;
|
||||
|
||||
if ((cur = tb[CL_ADD_UDP_PORT]) != NULL &&
|
||||
(ret = qosify_ubus_add_array(cur, dscp, CL_MAP_UDP_PORTS) != 0))
|
||||
return ret;
|
||||
|
||||
if ((cur = tb[CL_ADD_DNS]) != NULL &&
|
||||
(ret = qosify_ubus_add_array(cur, dscp, CL_MAP_DNS) != 0))
|
||||
return ret;
|
||||
|
||||
qosify_map_timeout = prev_timemout;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
enum {
|
||||
CL_CONFIG_RESET,
|
||||
CL_CONFIG_FILES,
|
||||
CL_CONFIG_TIMEOUT,
|
||||
CL_CONFIG_DSCP_UDP,
|
||||
CL_CONFIG_DSCP_TCP,
|
||||
CL_CONFIG_DSCP_PRIO,
|
||||
CL_CONFIG_DSCP_BULK,
|
||||
CL_CONFIG_DSCP_ICMP,
|
||||
CL_CONFIG_BULK_TIMEOUT,
|
||||
CL_CONFIG_BULK_PPS,
|
||||
CL_CONFIG_PRIO_PKT_LEN,
|
||||
CL_CONFIG_INTERFACES,
|
||||
CL_CONFIG_DEVICES,
|
||||
__CL_CONFIG_MAX
|
||||
};
|
||||
|
||||
static const struct blobmsg_policy qosify_config_policy[__CL_CONFIG_MAX] = {
|
||||
[CL_CONFIG_RESET] = { "reset", BLOBMSG_TYPE_BOOL },
|
||||
[CL_CONFIG_FILES] = { "files", BLOBMSG_TYPE_ARRAY },
|
||||
[CL_CONFIG_TIMEOUT] = { "timeout", BLOBMSG_TYPE_INT32 },
|
||||
[CL_CONFIG_DSCP_UDP] = { "dscp_default_udp", BLOBMSG_TYPE_STRING },
|
||||
[CL_CONFIG_DSCP_TCP] = { "dscp_default_tcp", BLOBMSG_TYPE_STRING },
|
||||
[CL_CONFIG_DSCP_PRIO] = { "dscp_prio", BLOBMSG_TYPE_STRING },
|
||||
[CL_CONFIG_DSCP_BULK] = { "dscp_bulk", BLOBMSG_TYPE_STRING },
|
||||
[CL_CONFIG_DSCP_ICMP] = { "dscp_icmp", BLOBMSG_TYPE_STRING },
|
||||
[CL_CONFIG_BULK_TIMEOUT] = { "bulk_trigger_timeout", BLOBMSG_TYPE_INT32 },
|
||||
[CL_CONFIG_BULK_PPS] = { "bulk_trigger_pps", BLOBMSG_TYPE_INT32 },
|
||||
[CL_CONFIG_PRIO_PKT_LEN] = { "prio_max_avg_pkt_len", BLOBMSG_TYPE_INT32 },
|
||||
[CL_CONFIG_INTERFACES] = { "interfaces", BLOBMSG_TYPE_TABLE },
|
||||
[CL_CONFIG_DEVICES] = { "devices", BLOBMSG_TYPE_TABLE },
|
||||
};
|
||||
|
||||
static int __set_dscp(uint8_t *dest, struct blob_attr *attr, bool reset)
|
||||
{
|
||||
int dscp;
|
||||
|
||||
if (reset)
|
||||
*dest = 0xff;
|
||||
|
||||
if (!attr)
|
||||
return 0;
|
||||
|
||||
dscp = qosify_map_dscp_value(blobmsg_get_string(attr));
|
||||
if (dscp < 0)
|
||||
return -1;
|
||||
|
||||
*dest = dscp;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
qosify_ubus_config(struct ubus_context *ctx, struct ubus_object *obj,
|
||||
struct ubus_request_data *req, const char *method,
|
||||
struct blob_attr *msg)
|
||||
{
|
||||
struct blob_attr *tb[__CL_CONFIG_MAX];
|
||||
struct blob_attr *cur;
|
||||
uint8_t dscp;
|
||||
bool reset = false;
|
||||
int ret;
|
||||
|
||||
blobmsg_parse(qosify_config_policy, __CL_CONFIG_MAX, tb,
|
||||
blobmsg_data(msg), blobmsg_len(msg));
|
||||
|
||||
if ((cur = tb[CL_CONFIG_RESET]) != NULL)
|
||||
reset = blobmsg_get_bool(cur);
|
||||
|
||||
if (reset)
|
||||
qosify_map_reset_config();
|
||||
|
||||
if ((cur = tb[CL_CONFIG_TIMEOUT]) != NULL)
|
||||
qosify_map_timeout = blobmsg_get_u32(cur);
|
||||
|
||||
if ((cur = tb[CL_CONFIG_FILES]) != NULL &&
|
||||
(ret = qosify_ubus_set_files(cur) != 0))
|
||||
return ret;
|
||||
|
||||
__set_dscp(&dscp, tb[CL_CONFIG_DSCP_UDP], true);
|
||||
if (dscp != 0xff)
|
||||
qosify_map_set_dscp_default(CL_MAP_UDP_PORTS, dscp);
|
||||
|
||||
__set_dscp(&dscp, tb[CL_CONFIG_DSCP_TCP], true);
|
||||
if (dscp != 0xff)
|
||||
qosify_map_set_dscp_default(CL_MAP_TCP_PORTS, dscp);
|
||||
|
||||
__set_dscp(&config.dscp_prio, tb[CL_CONFIG_DSCP_PRIO], reset);
|
||||
__set_dscp(&config.dscp_bulk, tb[CL_CONFIG_DSCP_BULK], reset);
|
||||
__set_dscp(&config.dscp_icmp, tb[CL_CONFIG_DSCP_ICMP], reset);
|
||||
|
||||
if ((cur = tb[CL_CONFIG_BULK_TIMEOUT]) != NULL)
|
||||
config.bulk_trigger_timeout = blobmsg_get_u32(cur);
|
||||
|
||||
if ((cur = tb[CL_CONFIG_BULK_PPS]) != NULL)
|
||||
config.bulk_trigger_pps = blobmsg_get_u32(cur);
|
||||
|
||||
if ((cur = tb[CL_CONFIG_PRIO_PKT_LEN]) != NULL)
|
||||
config.prio_max_avg_pkt_len = blobmsg_get_u32(cur);
|
||||
|
||||
qosify_map_update_config();
|
||||
|
||||
qosify_iface_config_update(tb[CL_CONFIG_INTERFACES], tb[CL_CONFIG_DEVICES]);
|
||||
|
||||
qosify_iface_check();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
qosify_ubus_dump(struct ubus_context *ctx, struct ubus_object *obj,
|
||||
struct ubus_request_data *req, const char *method,
|
||||
struct blob_attr *msg)
|
||||
{
|
||||
blob_buf_init(&b, 0);
|
||||
qosify_map_dump(&b);
|
||||
ubus_send_reply(ctx, req, b.head);
|
||||
blob_buf_free(&b);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
qosify_ubus_status(struct ubus_context *ctx, struct ubus_object *obj,
|
||||
struct ubus_request_data *req, const char *method,
|
||||
struct blob_attr *msg)
|
||||
{
|
||||
blob_buf_init(&b, 0);
|
||||
qosify_iface_status(&b);
|
||||
ubus_send_reply(ctx, req, b.head);
|
||||
blob_buf_free(&b);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
qosify_ubus_check_devices(struct ubus_context *ctx, struct ubus_object *obj,
|
||||
struct ubus_request_data *req, const char *method,
|
||||
struct blob_attr *msg)
|
||||
{
|
||||
qosify_iface_check();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
enum {
|
||||
CL_DNS_HOST_NAME,
|
||||
CL_DNS_HOST_TYPE,
|
||||
CL_DNS_HOST_ADDR,
|
||||
CL_DNS_HOST_TTL,
|
||||
__CL_DNS_HOST_MAX
|
||||
};
|
||||
|
||||
static const struct blobmsg_policy qosify_dns_policy[__CL_DNS_HOST_MAX] = {
|
||||
[CL_DNS_HOST_NAME] = { "name", BLOBMSG_TYPE_STRING },
|
||||
[CL_DNS_HOST_TYPE] = { "type", BLOBMSG_TYPE_STRING },
|
||||
[CL_DNS_HOST_ADDR] = { "address", BLOBMSG_TYPE_STRING },
|
||||
[CL_DNS_HOST_TTL] = { "ttl", BLOBMSG_TYPE_INT32 },
|
||||
};
|
||||
|
||||
static int
|
||||
qosify_ubus_add_dns_host(struct ubus_context *ctx, struct ubus_object *obj,
|
||||
struct ubus_request_data *req, const char *method,
|
||||
struct blob_attr *msg)
|
||||
{
|
||||
struct blob_attr *tb[__CL_DNS_HOST_MAX];
|
||||
struct blob_attr *cur;
|
||||
uint32_t ttl = 0;
|
||||
|
||||
blobmsg_parse(qosify_dns_policy, __CL_DNS_HOST_MAX, tb,
|
||||
blobmsg_data(msg), blobmsg_len(msg));
|
||||
|
||||
if (!tb[CL_DNS_HOST_NAME] || !tb[CL_DNS_HOST_TYPE] ||
|
||||
!tb[CL_DNS_HOST_ADDR])
|
||||
return UBUS_STATUS_INVALID_ARGUMENT;
|
||||
|
||||
if ((cur = tb[CL_DNS_HOST_TTL]) != NULL)
|
||||
ttl = blobmsg_get_u32(cur);
|
||||
|
||||
if (qosify_map_add_dns_host(blobmsg_get_string(tb[CL_DNS_HOST_NAME]),
|
||||
blobmsg_get_string(tb[CL_DNS_HOST_ADDR]),
|
||||
blobmsg_get_string(tb[CL_DNS_HOST_TYPE]),
|
||||
ttl))
|
||||
return UBUS_STATUS_INVALID_ARGUMENT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct ubus_method qosify_methods[] = {
|
||||
UBUS_METHOD_NOARG("reload", qosify_ubus_reload),
|
||||
UBUS_METHOD("add", qosify_ubus_add, qosify_add_policy),
|
||||
UBUS_METHOD_MASK("remove", qosify_ubus_add, qosify_add_policy,
|
||||
((1 << __CL_ADD_MAX) - 1) & ~(1 << CL_ADD_DSCP)),
|
||||
UBUS_METHOD("config", qosify_ubus_config, qosify_config_policy),
|
||||
UBUS_METHOD_NOARG("dump", qosify_ubus_dump),
|
||||
UBUS_METHOD_NOARG("status", qosify_ubus_status),
|
||||
UBUS_METHOD("add_dns_host", qosify_ubus_add_dns_host, qosify_dns_policy),
|
||||
UBUS_METHOD_NOARG("check_devices", qosify_ubus_check_devices),
|
||||
};
|
||||
|
||||
static struct ubus_object_type qosify_object_type =
|
||||
UBUS_OBJECT_TYPE("qosify", qosify_methods);
|
||||
|
||||
static struct ubus_object qosify_object = {
|
||||
.name = "qosify",
|
||||
.type = &qosify_object_type,
|
||||
.methods = qosify_methods,
|
||||
.n_methods = ARRAY_SIZE(qosify_methods),
|
||||
};
|
||||
|
||||
static void
|
||||
ubus_connect_handler(struct ubus_context *ctx)
|
||||
{
|
||||
ubus_add_object(ctx, &qosify_object);
|
||||
}
|
||||
|
||||
static struct ubus_auto_conn conn;
|
||||
|
||||
int qosify_ubus_init(void)
|
||||
{
|
||||
conn.cb = ubus_connect_handler;
|
||||
ubus_auto_connect(&conn);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void qosify_ubus_stop(void)
|
||||
{
|
||||
ubus_auto_shutdown(&conn);
|
||||
}
|
||||
|
||||
struct iface_req {
|
||||
char *name;
|
||||
int len;
|
||||
};
|
||||
|
||||
static void
|
||||
netifd_if_cb(struct ubus_request *req, int type, struct blob_attr *msg)
|
||||
{
|
||||
struct iface_req *ifr = req->priv;
|
||||
enum {
|
||||
IFS_ATTR_UP,
|
||||
IFS_ATTR_DEV,
|
||||
__IFS_ATTR_MAX
|
||||
};
|
||||
static const struct blobmsg_policy policy[__IFS_ATTR_MAX] = {
|
||||
[IFS_ATTR_UP] = { "up", BLOBMSG_TYPE_BOOL },
|
||||
[IFS_ATTR_DEV] = { "l3_device", BLOBMSG_TYPE_STRING },
|
||||
};
|
||||
struct blob_attr *tb[__IFS_ATTR_MAX];
|
||||
|
||||
blobmsg_parse(policy, __IFS_ATTR_MAX, tb, blobmsg_data(msg), blobmsg_len(msg));
|
||||
|
||||
if (!tb[IFS_ATTR_UP] || !tb[IFS_ATTR_DEV])
|
||||
return;
|
||||
|
||||
if (!blobmsg_get_bool(tb[IFS_ATTR_UP]))
|
||||
return;
|
||||
|
||||
snprintf(ifr->name, ifr->len, "%s", blobmsg_get_string(tb[IFS_ATTR_DEV]));
|
||||
}
|
||||
|
||||
int qosify_ubus_check_interface(const char *name, char *ifname, int ifname_len)
|
||||
{
|
||||
struct iface_req req = { ifname, ifname_len };
|
||||
char *obj_name = "network.interface.";
|
||||
uint32_t id;
|
||||
|
||||
#define PREFIX "network.interface."
|
||||
obj_name = alloca(sizeof(PREFIX) + strlen(name) + 1);
|
||||
sprintf(obj_name, PREFIX "%s", name);
|
||||
#undef PREFIX
|
||||
|
||||
ifname[0] = 0;
|
||||
|
||||
if (ubus_lookup_id(&conn.ctx, obj_name, &id))
|
||||
return -1;
|
||||
|
||||
ubus_invoke(&conn.ctx, id, "status", b.head, netifd_if_cb, &req, 1000);
|
||||
|
||||
if (!ifname[0])
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
25
feeds/ucentral/radius-gw-proxy/Makefile
Normal file
25
feeds/ucentral/radius-gw-proxy/Makefile
Normal file
@@ -0,0 +1,25 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=radius-gw-proxy
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_LICENSE:=BSD-3-Clause
|
||||
PKG_MAINTAINER:=John Crispin <john@phrozen.org>
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
include $(INCLUDE_DIR)/cmake.mk
|
||||
|
||||
define Package/radius-gw-proxy
|
||||
SECTION:=ucentral
|
||||
CATEGORY:=uCentral
|
||||
TITLE:=uCentral Gateway radius-gw-proxy
|
||||
DEPENDS:=+libubox +libubus
|
||||
endef
|
||||
|
||||
define Package/radius-gw-proxy/install
|
||||
$(INSTALL_DIR) $(1)/usr/sbin
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/radius-gw-proxy $(1)/usr/sbin/
|
||||
$(CP) ./files/* $(1)
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,radius-gw-proxy))
|
||||
11
feeds/ucentral/radius-gw-proxy/files/etc/init.d/radius-gw-proxy
Executable file
11
feeds/ucentral/radius-gw-proxy/files/etc/init.d/radius-gw-proxy
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
|
||||
START=99
|
||||
|
||||
USE_PROCD=1
|
||||
|
||||
start_service() {
|
||||
procd_open_instance
|
||||
procd_set_param command "/usr/sbin/radius-gw-proxy"
|
||||
procd_close_instance
|
||||
}
|
||||
30
feeds/ucentral/radius-gw-proxy/src/CMakeLists.txt
Normal file
30
feeds/ucentral/radius-gw-proxy/src/CMakeLists.txt
Normal file
@@ -0,0 +1,30 @@
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
|
||||
PROJECT(radius-gw-proxy C)
|
||||
|
||||
ADD_DEFINITIONS(-Wall -Werror)
|
||||
IF(CMAKE_C_COMPILER_VERSION VERSION_GREATER 6)
|
||||
ADD_DEFINITIONS(-Wextra -Werror=implicit-function-declaration)
|
||||
ADD_DEFINITIONS(-Wformat -Werror=format-security -Werror=format-nonliteral)
|
||||
ENDIF()
|
||||
ADD_DEFINITIONS(-Os -std=gnu99 -g3 -Wmissing-declarations -Wno-unused-parameter -Wno-strict-aliasing)
|
||||
|
||||
SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
|
||||
|
||||
SET(SOURCES main.c ubus.c)
|
||||
|
||||
FIND_LIBRARY(ubus NAMES ubus)
|
||||
FIND_LIBRARY(ubox NAMES ubox)
|
||||
|
||||
FIND_PATH(ubox_include_dir libubox/uloop.h)
|
||||
FIND_PATH(ubus_include_dir NAMES libubus.h)
|
||||
|
||||
INCLUDE_DIRECTORIES(${ubox_include_dir} ${ubus_include_dir})
|
||||
|
||||
ADD_EXECUTABLE(radius-gw-proxy ${SOURCES})
|
||||
|
||||
TARGET_LINK_LIBRARIES(radius-gw-proxy ${ubox} ${ubus})
|
||||
|
||||
INSTALL(TARGETS radius-gw-proxy
|
||||
RUNTIME DESTINATION sbin
|
||||
)
|
||||
363
feeds/ucentral/radius-gw-proxy/src/main.c
Normal file
363
feeds/ucentral/radius-gw-proxy/src/main.c
Normal file
@@ -0,0 +1,363 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <net/if.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <libubox/uloop.h>
|
||||
#include <libubox/usock.h>
|
||||
#include <libubox/ulog.h>
|
||||
|
||||
#include <libubus.h>
|
||||
|
||||
#include "ubus.h"
|
||||
|
||||
#define RAD_PROX_BUFLEN (4 * 1024)
|
||||
|
||||
#define TLV_NAS_IP 4
|
||||
#define TLV_PROXY_STATE 33
|
||||
|
||||
struct radius_socket {
|
||||
struct uloop_fd fd;
|
||||
enum socket_type type;
|
||||
};
|
||||
|
||||
struct radius_header {
|
||||
uint8_t code;
|
||||
uint8_t id;
|
||||
uint16_t len;
|
||||
char auth[16];
|
||||
char avp[];
|
||||
};
|
||||
|
||||
struct radius_tlv {
|
||||
uint8_t id;
|
||||
uint8_t len;
|
||||
char data[];
|
||||
};
|
||||
|
||||
struct radius_proxy_state_key {
|
||||
char id[256];
|
||||
enum socket_type type;
|
||||
};
|
||||
|
||||
struct radius_proxy_state {
|
||||
struct avl_node avl;
|
||||
struct radius_proxy_state_key key;
|
||||
int port;
|
||||
};
|
||||
|
||||
static struct radius_socket *sock_auth;
|
||||
static struct radius_socket *sock_acct;
|
||||
static struct radius_socket *sock_dae;
|
||||
|
||||
static int
|
||||
avl_memcmp(const void *k1, const void *k2, void *ptr)
|
||||
{
|
||||
return memcmp(k1, k2, sizeof(struct radius_proxy_state_key));
|
||||
}
|
||||
|
||||
static AVL_TREE(radius_proxy_states, avl_memcmp, false, NULL);
|
||||
static struct blob_buf b;
|
||||
|
||||
static void
|
||||
radius_proxy_state_add(char *id, int port, enum socket_type type)
|
||||
{
|
||||
struct radius_proxy_state *station;
|
||||
struct radius_proxy_state_key key = { .type = type };
|
||||
|
||||
strcpy(key.id, id);
|
||||
station = avl_find_element(&radius_proxy_states, &key, station, avl);
|
||||
|
||||
if (!station) {
|
||||
ULOG_INFO("new station/port, adding to avl tree\n");
|
||||
station = malloc(sizeof(*station));
|
||||
memset(station, 0, sizeof(*station));
|
||||
strcpy(station->key.id, id);
|
||||
station->key.type = type;
|
||||
station->avl.key = &station->key;
|
||||
avl_insert(&radius_proxy_states, &station->avl);
|
||||
}
|
||||
station->port = port;
|
||||
}
|
||||
|
||||
static char *
|
||||
b64enc(char *src, int len)
|
||||
{
|
||||
char *dst;
|
||||
int ret;
|
||||
|
||||
if (!src)
|
||||
return NULL;
|
||||
dst = malloc(len * 4);
|
||||
ret = b64_encode(src, len, dst, len * 4);
|
||||
if (ret < 1) {
|
||||
free(dst);
|
||||
return NULL;
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
static char *
|
||||
b64dec(char *src, int *ret)
|
||||
{
|
||||
int len = strlen(src);
|
||||
char *dst = malloc(len);
|
||||
*ret = b64_decode(src, dst, len);
|
||||
if (*ret < 0)
|
||||
return NULL;
|
||||
return dst;
|
||||
}
|
||||
|
||||
static void
|
||||
radius_forward_gw(char *buf, enum socket_type type)
|
||||
{
|
||||
struct radius_header *hdr = (struct radius_header *) buf;
|
||||
struct ubus_request async = { };
|
||||
char *data = b64enc(buf, ntohs(hdr->len));
|
||||
|
||||
if (!data || !ucentral)
|
||||
return;
|
||||
|
||||
blob_buf_init(&b, 0);
|
||||
switch (type) {
|
||||
case RADIUS_AUTH:
|
||||
blobmsg_add_string(&b, "radius", "auth");
|
||||
break;
|
||||
case RADIUS_ACCT:
|
||||
blobmsg_add_string(&b, "radius", "acct");
|
||||
break;
|
||||
case RADIUS_DAS:
|
||||
blobmsg_add_string(&b, "radius", "coa");
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
blobmsg_add_string(&b, "data", data);
|
||||
|
||||
ubus_invoke_async(&conn.ctx, ucentral, "radius", b.head, &async);
|
||||
ubus_abort_request(&conn.ctx, &async);
|
||||
|
||||
free(data);
|
||||
}
|
||||
|
||||
static int
|
||||
radius_parse(char *buf, int len, int port, enum socket_type type, int tx)
|
||||
{
|
||||
struct radius_header *hdr = (struct radius_header *) buf;
|
||||
struct radius_tlv *proxy_state = NULL;
|
||||
char proxy_state_str[256] = {};
|
||||
void *avp = hdr->avp;
|
||||
int len_orig = ntohs(hdr->len);
|
||||
uint8_t localhost[] = { 0x7f, 0, 0, 1 };
|
||||
|
||||
if (len_orig != len) {
|
||||
ULOG_ERR("invalid header length, %d %d\n", len_orig, len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("\tcode:%d, id:%d, len:%d\n", hdr->code, hdr->id, len_orig);
|
||||
|
||||
len -= sizeof(*hdr);
|
||||
|
||||
while (len > 0) {
|
||||
struct radius_tlv *tlv = (struct radius_tlv *)avp;
|
||||
|
||||
if (len < tlv->len) {
|
||||
ULOG_ERR("invalid TLV length\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tlv->id == TLV_PROXY_STATE)
|
||||
proxy_state = tlv;
|
||||
|
||||
if (type == RADIUS_DAS && tlv->id == TLV_NAS_IP && tlv->len == 6)
|
||||
memcpy(tlv->data, &localhost, 4);
|
||||
|
||||
printf("\tID:%d, len:%d\n", tlv->id, tlv->len);
|
||||
avp += tlv->len;
|
||||
len -= tlv->len;
|
||||
}
|
||||
|
||||
if (type == RADIUS_DAS) {
|
||||
if (tx) {
|
||||
radius_forward_gw(buf, type);
|
||||
} else {
|
||||
struct sockaddr_in dest;
|
||||
|
||||
memset(&dest, 0, sizeof(dest));
|
||||
dest.sin_family = AF_INET;
|
||||
dest.sin_port = htons(3799);
|
||||
inet_pton(AF_INET, "127.0.0.1", &(dest.sin_addr.s_addr));
|
||||
|
||||
if (sendto(sock_dae->fd.fd, buf, len_orig,
|
||||
MSG_DONTWAIT, (struct sockaddr*)&dest, sizeof(dest)) < 0)
|
||||
ULOG_ERR("failed to deliver DAS frame to localhost\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!proxy_state) {
|
||||
ULOG_ERR("no proxy_state found\n");
|
||||
return -1;
|
||||
}
|
||||
memcpy(proxy_state_str, proxy_state->data, proxy_state->len - 2);
|
||||
printf("\tfowarding to %s, prox_state:%s\n", tx ? "gateway" : "hostapd", proxy_state_str);
|
||||
if (tx) {
|
||||
radius_proxy_state_add(proxy_state_str, port, type);
|
||||
radius_forward_gw(buf, type);
|
||||
} else {
|
||||
struct radius_proxy_state *proxy = avl_find_element(&radius_proxy_states, proxy_state, proxy, avl);
|
||||
struct radius_proxy_state_key key = {};
|
||||
struct sockaddr_in dest;
|
||||
struct radius_socket *sock;
|
||||
|
||||
switch(type) {
|
||||
case RADIUS_AUTH:
|
||||
sock = sock_auth;
|
||||
break;
|
||||
|
||||
case RADIUS_ACCT:
|
||||
sock = sock_acct;
|
||||
break;
|
||||
default:
|
||||
ULOG_ERR("bad socket type\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
strcpy(key.id, proxy_state_str);
|
||||
key.type = type;
|
||||
proxy = avl_find_element(&radius_proxy_states, &key, proxy, avl);
|
||||
|
||||
if (!proxy) {
|
||||
ULOG_ERR("unknown proxy_state, dropping frame\n");
|
||||
return -1;
|
||||
}
|
||||
memset(&dest, 0, sizeof(dest));
|
||||
dest.sin_family = AF_INET;
|
||||
dest.sin_port = proxy->port;
|
||||
inet_pton(AF_INET, "127.0.0.1", &(dest.sin_addr.s_addr));
|
||||
|
||||
if (sendto(sock->fd.fd, buf, len_orig,
|
||||
MSG_DONTWAIT, (struct sockaddr*)&dest, sizeof(dest)) < 0)
|
||||
ULOG_ERR("failed to deliver frame to localhost\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
gateway_recv(char *data, enum socket_type type)
|
||||
{
|
||||
int len = 0;
|
||||
char *frame;
|
||||
|
||||
frame = b64dec(data, &len);
|
||||
|
||||
if (!frame) {
|
||||
ULOG_ERR("failed to b64_decode frame\n");
|
||||
return;
|
||||
}
|
||||
|
||||
radius_parse(frame, len, 0, type, 0);
|
||||
free(frame);
|
||||
}
|
||||
|
||||
static void
|
||||
sock_recv(struct uloop_fd *u, unsigned int events)
|
||||
{
|
||||
static char buf[RAD_PROX_BUFLEN];
|
||||
static char cmsg_buf[( CMSG_SPACE(sizeof(struct in_pktinfo)) + sizeof(int)) + 1];
|
||||
static struct sockaddr_in sin;
|
||||
char addr_str[INET_ADDRSTRLEN];
|
||||
static struct iovec iov = {
|
||||
.iov_base = buf,
|
||||
.iov_len = sizeof(buf)
|
||||
};
|
||||
static struct msghdr msg = {
|
||||
.msg_name = &sin,
|
||||
.msg_namelen = sizeof(sin),
|
||||
.msg_iov = &iov,
|
||||
.msg_iovlen = 1,
|
||||
.msg_control = cmsg_buf,
|
||||
.msg_controllen = sizeof(cmsg_buf),
|
||||
};
|
||||
struct radius_socket *sock = container_of(u, struct radius_socket, fd);
|
||||
int len;
|
||||
|
||||
do {
|
||||
len = recvmsg(u->fd, &msg, 0);
|
||||
if (len < 0) {
|
||||
switch (errno) {
|
||||
case EAGAIN:
|
||||
return;
|
||||
case EINTR:
|
||||
continue;
|
||||
default:
|
||||
perror("recvmsg");
|
||||
uloop_fd_delete(u);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
inet_ntop(AF_INET, &sin.sin_addr, addr_str, sizeof(addr_str));
|
||||
printf("RX: src:%s:%d, len=%d\n", addr_str, sin.sin_port, len);
|
||||
radius_parse(buf, len, sin.sin_port, sock->type, 1);
|
||||
} while (1);
|
||||
}
|
||||
|
||||
static struct radius_socket *
|
||||
sock_open(char *port, enum socket_type type)
|
||||
{
|
||||
struct radius_socket *sock = malloc(sizeof(*sock));
|
||||
|
||||
if (!sock)
|
||||
return NULL;
|
||||
|
||||
memset(sock, 0, sizeof(*sock));
|
||||
|
||||
sock->fd.fd = usock(USOCK_UDP | USOCK_SERVER | USOCK_NONBLOCK |
|
||||
USOCK_NUMERIC | USOCK_IPV4ONLY,
|
||||
"127.0.0.1", port);
|
||||
if (sock->fd.fd < 0) {
|
||||
perror("usock");
|
||||
free(sock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sock->type = type;
|
||||
sock->fd.cb = sock_recv;
|
||||
|
||||
uloop_fd_add(&sock->fd, ULOOP_READ);
|
||||
|
||||
return sock;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
ulog_open(ULOG_STDIO | ULOG_SYSLOG, LOG_DAEMON, "radius-gw-proxy");
|
||||
|
||||
uloop_init();
|
||||
|
||||
ubus_init();
|
||||
|
||||
sock_auth = sock_open("1812", RADIUS_AUTH);
|
||||
sock_acct = sock_open("1813", RADIUS_ACCT);
|
||||
sock_dae = sock_open("1814", RADIUS_DAS);
|
||||
|
||||
uloop_run();
|
||||
uloop_end();
|
||||
ubus_deinit();
|
||||
|
||||
return 0;
|
||||
}
|
||||
124
feeds/ucentral/radius-gw-proxy/src/ubus.c
Normal file
124
feeds/ucentral/radius-gw-proxy/src/ubus.c
Normal file
@@ -0,0 +1,124 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <libubox/ulog.h>
|
||||
#include <libubus.h>
|
||||
#include "ubus.h"
|
||||
|
||||
struct ubus_auto_conn conn;
|
||||
uint32_t ucentral;
|
||||
|
||||
enum {
|
||||
RADIUS_TYPE,
|
||||
RADIUS_DATA,
|
||||
__RADIUS_MAX,
|
||||
};
|
||||
|
||||
static const struct blobmsg_policy frame_policy[__RADIUS_MAX] = {
|
||||
[RADIUS_TYPE] = { .name = "radius", .type = BLOBMSG_TYPE_STRING },
|
||||
[RADIUS_DATA] = { .name = "data", .type = BLOBMSG_TYPE_STRING },
|
||||
};
|
||||
|
||||
static int ubus_frame_cb(struct ubus_context *ctx,
|
||||
struct ubus_object *obj,
|
||||
struct ubus_request_data *req,
|
||||
const char *method, struct blob_attr *msg)
|
||||
{
|
||||
struct blob_attr *tb[__RADIUS_MAX] = {};
|
||||
enum socket_type type;
|
||||
char *radius, *data;
|
||||
|
||||
blobmsg_parse(frame_policy, __RADIUS_MAX, tb, blobmsg_data(msg), blobmsg_data_len(msg));
|
||||
if (!tb[RADIUS_TYPE] || !tb[RADIUS_DATA])
|
||||
return UBUS_STATUS_INVALID_ARGUMENT;
|
||||
|
||||
radius = blobmsg_get_string(tb[RADIUS_TYPE]);
|
||||
data = blobmsg_get_string(tb[RADIUS_DATA]);
|
||||
|
||||
if (!strcmp(radius, "auth"))
|
||||
type = RADIUS_AUTH;
|
||||
else if (!strcmp(radius, "acct"))
|
||||
type = RADIUS_ACCT;
|
||||
else if (!strcmp(radius, "coa"))
|
||||
type = RADIUS_DAS;
|
||||
else
|
||||
return UBUS_STATUS_INVALID_ARGUMENT;
|
||||
|
||||
gateway_recv(data, type);
|
||||
|
||||
return UBUS_STATUS_OK;
|
||||
}
|
||||
static const struct ubus_method ucentral_methods[] = {
|
||||
UBUS_METHOD("frame", ubus_frame_cb, frame_policy),
|
||||
};
|
||||
|
||||
static struct ubus_object_type ubus_object_type =
|
||||
UBUS_OBJECT_TYPE("radius.proxy", ucentral_methods);
|
||||
|
||||
struct ubus_object ubus_object = {
|
||||
.name = "radius.proxy",
|
||||
.type = &ubus_object_type,
|
||||
.methods = ucentral_methods,
|
||||
.n_methods = ARRAY_SIZE(ucentral_methods),
|
||||
};
|
||||
|
||||
static void
|
||||
ubus_event_handler_cb(struct ubus_context *ctx, struct ubus_event_handler *ev,
|
||||
const char *type, struct blob_attr *msg)
|
||||
{
|
||||
enum {
|
||||
EVENT_ID,
|
||||
EVENT_PATH,
|
||||
__EVENT_MAX
|
||||
};
|
||||
|
||||
static const struct blobmsg_policy status_policy[__EVENT_MAX] = {
|
||||
[EVENT_ID] = { .name = "id", .type = BLOBMSG_TYPE_INT32 },
|
||||
[EVENT_PATH] = { .name = "path", .type = BLOBMSG_TYPE_STRING },
|
||||
};
|
||||
|
||||
struct blob_attr *tb[__EVENT_MAX];
|
||||
char *path;
|
||||
uint32_t id;
|
||||
|
||||
blobmsg_parse(status_policy, __EVENT_MAX, tb, blob_data(msg), blob_len(msg));
|
||||
|
||||
if (!tb[EVENT_ID] || !tb[EVENT_PATH])
|
||||
return;
|
||||
|
||||
path = blobmsg_get_string(tb[EVENT_PATH]);
|
||||
id = blobmsg_get_u32(tb[EVENT_ID]);
|
||||
|
||||
if (strcmp(path, "ucentral"))
|
||||
return;
|
||||
if (!strcmp("ubus.object.remove", type))
|
||||
ucentral = 0;
|
||||
else
|
||||
ucentral = id;
|
||||
}
|
||||
|
||||
static struct ubus_event_handler ubus_event_handler = { .cb = ubus_event_handler_cb };
|
||||
|
||||
static void
|
||||
ubus_connect_handler(struct ubus_context *ctx)
|
||||
{
|
||||
ubus_add_object(ctx, &ubus_object);
|
||||
ubus_register_event_handler(ctx, &ubus_event_handler, "ubus.object.add");
|
||||
ubus_register_event_handler(ctx, &ubus_event_handler, "ubus.object.remove");
|
||||
|
||||
ubus_lookup_id(ctx, "ucentral", &ucentral);
|
||||
}
|
||||
|
||||
void ubus_init(void)
|
||||
{
|
||||
memset(&conn, 0, sizeof(conn));
|
||||
ucentral = 0;
|
||||
conn.cb = ubus_connect_handler;
|
||||
ubus_auto_connect(&conn);
|
||||
}
|
||||
|
||||
void ubus_deinit(void)
|
||||
{
|
||||
ubus_auto_shutdown(&conn);
|
||||
}
|
||||
13
feeds/ucentral/radius-gw-proxy/src/ubus.h
Normal file
13
feeds/ucentral/radius-gw-proxy/src/ubus.h
Normal file
@@ -0,0 +1,13 @@
|
||||
enum socket_type {
|
||||
RADIUS_AUTH = 0,
|
||||
RADIUS_ACCT,
|
||||
RADIUS_DAS
|
||||
};
|
||||
|
||||
extern struct ubus_auto_conn conn;
|
||||
extern uint32_t ucentral;
|
||||
|
||||
void ubus_init(void);
|
||||
void ubus_deinit(void);
|
||||
void gateway_recv(char *data, enum socket_type type);
|
||||
|
||||
@@ -101,6 +101,7 @@ deliface() {
|
||||
|
||||
found=0
|
||||
find_ssid() {
|
||||
local ssid
|
||||
config_get ssid $1 ssid
|
||||
[ "$ssid" == "$2" ] || return
|
||||
found=1
|
||||
@@ -119,7 +120,7 @@ addiface() {
|
||||
echo -n startup > /tmp/ratelimit.$iface
|
||||
|
||||
sleep 2
|
||||
ssid=$(ubus call network.wireless status | jsonfilter -e '@[*].interfaces[@.ifname="'"$iface"'"].config.ssid')
|
||||
ssid=$(ubus call hostapd.$iface get_status | jsonfilter -e '@.ssid')
|
||||
[ -z "$ssid" ] && {
|
||||
rm /tmp/ratelimit.$iface
|
||||
logger "ratelimit: failed to lookup ssid"
|
||||
|
||||
@@ -3,10 +3,11 @@ include $(TOPDIR)/rules.mk
|
||||
PKG_NAME:=ucentral-client
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE_URL=https://github.com/blogic/ucentral-client.git
|
||||
PKG_SOURCE_URL=https://github.com/Telecominfraproject/wlan-ucentral-client.git
|
||||
PKG_MIRROR_HASH:=2fc20dd3b5c8a7d93e17a843a2feaa823a6f8e902fdca96df62aa3f12efdfbaa
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_DATE:=2022-01-10
|
||||
PKG_SOURCE_VERSION:=e3b71c61e1a07bb3b5fa34fe835fd8f6f708caa3
|
||||
PKG_SOURCE_DATE:=2022-06-22
|
||||
PKG_SOURCE_VERSION:=68fe6c21f2c2643de79ecd5558a51ffb84168f75
|
||||
|
||||
PKG_LICENSE:=BSD-3-Clause
|
||||
PKG_MAINTAINER:=John Crispin <john@phrozen.org>
|
||||
@@ -18,7 +19,7 @@ define Package/ucentral-client
|
||||
SECTION:=ucentral
|
||||
CATEGORY:=uCentral
|
||||
TITLE:=OpenWrt uCentral websocket client
|
||||
DEPENDS:=+ucode +ucode-mod-fs +ucode-mod-ubus +ucode-mod-uci +ucode-mod-math +ucode-mod-resolv \
|
||||
DEPENDS:=+ucode +ucode-mod-fs +ucode-mod-ubus +ucode-mod-uci +ucode-mod-math +ucode-mod-resolv +ucode-mod-uloop \
|
||||
+libubox +libwebsockets-openssl +libblobmsg-json +libubus
|
||||
endef
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ start_service() {
|
||||
|
||||
mkdir -p /tmp/ucentral/
|
||||
|
||||
ucode -m fs -i /usr/share/ucentral/crashlog.uc
|
||||
ucode -l fs /usr/share/ucentral/crashlog.uc
|
||||
|
||||
. /lib/functions.sh
|
||||
cp /etc/config-shadow/ucentral /etc/config/
|
||||
@@ -32,8 +32,6 @@ start_service() {
|
||||
config_get debug 'config' 'debug' 0
|
||||
config_get insecure 'config' 'insecure' 0
|
||||
|
||||
interval=$(uci get ustats.health.interval)
|
||||
|
||||
procd_open_instance
|
||||
procd_set_param command "$PROG"
|
||||
[ -n "$serial" ] && procd_append_param command -S $serial
|
||||
@@ -41,7 +39,6 @@ start_service() {
|
||||
[ -n "$port" ] && procd_append_param command -P $port
|
||||
[ "$debug" -eq 0 ] || procd_append_param command -d
|
||||
[ "$insecure" -eq 0 ] || procd_append_param command -i
|
||||
[ -z "$interval" ] || procd_append_param command -H $interval
|
||||
[ -z "$(mount | grep 'tmpfs on / type tmpfs')" ] || procd_append_param command -r
|
||||
procd_append_param command -f "$(cat /tmp/ucentral.version)"
|
||||
procd_set_param respawn 3600 5 0
|
||||
|
||||
29
feeds/ucentral/ucentral-client/files/etc/init.d/uhealth
Executable file
29
feeds/ucentral/ucentral-client/files/etc/init.d/uhealth
Executable file
@@ -0,0 +1,29 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
|
||||
START=99
|
||||
|
||||
USE_PROCD=1
|
||||
PROG=/usr/share/ucentral/health.uc
|
||||
|
||||
boot() {
|
||||
# dummy stub to make sure health does not start before
|
||||
# a config is applied
|
||||
true
|
||||
}
|
||||
|
||||
service_triggers() {
|
||||
procd_add_reload_trigger ustats
|
||||
}
|
||||
|
||||
start_service() {
|
||||
. /lib/functions.sh
|
||||
config_load 'ustats'
|
||||
config_get interval 'health' 'interval' 120
|
||||
|
||||
[ "$interval" -eq 0 ] || {
|
||||
procd_open_instance
|
||||
procd_set_param command "$PROG"
|
||||
procd_set_param respawn 1 $interval 0
|
||||
procd_close_instance
|
||||
}
|
||||
}
|
||||
@@ -20,9 +20,4 @@ start_service() {
|
||||
procd_set_param respawn 1 $interval 0
|
||||
procd_close_instance
|
||||
}
|
||||
|
||||
config_get interval 'health' 'interval' 0
|
||||
[ "$interval" -eq 0 ] || {
|
||||
ubus call ucentral config '{"health": '$interval' }'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,9 +4,10 @@ PKG_NAME:=ucentral-event
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE_URL=https://github.com/blogic/ucentral-event.git
|
||||
PKG_MIRROR_HASH:=8cb470d7cc6c458fe748ee6f54e4bf79bec5500735d7b992d83c1aa10f700c6b
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_DATE:=2021-04-13
|
||||
PKG_SOURCE_VERSION:=7b0d136e8556bb099d7032823139d275448714cb
|
||||
PKG_SOURCE_VERSION:=24b7fb36e456d99b470c212674b3bf50bac64c74
|
||||
|
||||
PKG_MAINTAINER:=John Crispin <john@phrozen.org>
|
||||
PKG_LICENSE:=BSD-3-Clause
|
||||
|
||||
@@ -3,10 +3,11 @@ include $(TOPDIR)/rules.mk
|
||||
PKG_NAME:=ucentral-schema
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE_URL=https://github.com/blogic/ucentral-schema.git
|
||||
PKG_SOURCE_URL=https://github.com/Telecominfraproject/wlan-ucentral-schema.git
|
||||
PKG_MIRROR_HASH:=3603ddd26026d3a5b0febe7fbae22fd28fd6d7370793ecf979561d8886be2af4
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_DATE:=2022-01-17
|
||||
PKG_SOURCE_VERSION:=07cb6e9fc7a4a8f9868e6efd29edcaf1f3245716
|
||||
PKG_SOURCE_DATE:=2022-05-29
|
||||
PKG_SOURCE_VERSION:=9691cc6860c25ba7d62142846da44bd09c17acc0
|
||||
|
||||
PKG_MAINTAINER:=John Crispin <john@phrozen.org>
|
||||
PKG_LICENSE:=BSD-3-Clause
|
||||
|
||||
@@ -6,9 +6,9 @@ USE_PROCD=1
|
||||
PROG=/usr/bin/ucode
|
||||
|
||||
start_service() {
|
||||
local interval=$(uci get onlinecheck.@config.check_interval)
|
||||
local interval=$(uci get onlinecheck.@config[-1].check_interval)
|
||||
procd_open_instance
|
||||
procd_set_param command "$PROG" -m uci -m fs -i /usr/share/ucentral/onlinecheck.uc
|
||||
procd_set_param command "$PROG" -l uci -l fs /usr/share/ucentral/onlinecheck.uc
|
||||
procd_set_param respawn 1 $interval 0
|
||||
procd_close_instance
|
||||
}
|
||||
|
||||
@@ -1,23 +1,12 @@
|
||||
{
|
||||
"uuid": 2,
|
||||
"radios": [
|
||||
{
|
||||
"band": "6G",
|
||||
"country": "CA",
|
||||
"channel-mode": "HE",
|
||||
"channel-width": 80
|
||||
},
|
||||
{
|
||||
"band": "5G",
|
||||
"country": "CA",
|
||||
"channel-mode": "HE",
|
||||
"channel-width": 80
|
||||
},
|
||||
{
|
||||
"band": "2G",
|
||||
"country": "CA",
|
||||
"channel-mode": "HE",
|
||||
"channel-width": 80
|
||||
"channel-width": 20,
|
||||
"channel": 1
|
||||
}
|
||||
],
|
||||
|
||||
@@ -44,8 +33,27 @@
|
||||
},
|
||||
"tunnel": {
|
||||
"proto": "gre",
|
||||
"peer-address": "50.210.104.108"
|
||||
}
|
||||
"peer-address": "192.168.178.59"
|
||||
},
|
||||
"ipv4": {
|
||||
"addressing": "static",
|
||||
"subnet": "192.168.2.2/24",
|
||||
"gateway": "192.168.2.1"
|
||||
},
|
||||
"ssids": [
|
||||
{
|
||||
"name": "OpenWifi-GRE",
|
||||
"wifi-bands": [
|
||||
"2G"
|
||||
],
|
||||
"bss-mode": "ap",
|
||||
"encryption": {
|
||||
"proto": "psk2",
|
||||
"key": "OpenWifi",
|
||||
"ieee80211w": "optional"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "LAN",
|
||||
@@ -69,19 +77,15 @@
|
||||
},
|
||||
"ssids": [
|
||||
{
|
||||
"name": "Maverick",
|
||||
"name": "OpenWifi-GRE-NAT",
|
||||
"wifi-bands": [
|
||||
"5G",
|
||||
"2G"
|
||||
],
|
||||
"bss-mode": "ap",
|
||||
"encryption": {
|
||||
"proto": "none",
|
||||
"proto": "psk2",
|
||||
"key": "OpenWifi",
|
||||
"ieee80211w": "optional"
|
||||
},
|
||||
"roaming": {
|
||||
"message-exchange": "ds",
|
||||
"generate-psk": true
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -97,7 +97,7 @@
|
||||
"online-check": {
|
||||
"ping-hosts": [
|
||||
"192.168.178.1",
|
||||
"uecntral.io"
|
||||
"ucentral.io"
|
||||
],
|
||||
"download-hosts": [
|
||||
"ucentral.io"
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
{
|
||||
"uuid": 2,
|
||||
"radios": [
|
||||
{
|
||||
"band": "2G",
|
||||
"country": "CA",
|
||||
"channel-mode": "HE",
|
||||
"channel-width": 20,
|
||||
"channel": 6
|
||||
}
|
||||
],
|
||||
|
||||
"interfaces": [
|
||||
{
|
||||
"name": "WAN",
|
||||
"role": "upstream",
|
||||
"services": [ "ssh" ],
|
||||
"ethernet": [
|
||||
{
|
||||
"select-ports": [
|
||||
"WAN*"
|
||||
]
|
||||
}
|
||||
],
|
||||
"ipv4": {
|
||||
"addressing": "dynamic"
|
||||
},
|
||||
"ssids": [
|
||||
{
|
||||
"name": "OpenWifi",
|
||||
"wifi-bands": [
|
||||
"2G"
|
||||
],
|
||||
"bss-mode": "ap",
|
||||
"encryption": {
|
||||
"proto": "psk2-radius",
|
||||
"ieee80211w": "optional"
|
||||
},
|
||||
"radius": {
|
||||
"authentication": {
|
||||
"host": "192.168.50.30",
|
||||
"port": 1812,
|
||||
"secret": "secret"
|
||||
},
|
||||
"accounting": {
|
||||
"host": "192.168.50.30",
|
||||
"port": 1813,
|
||||
"secret": "secret"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "LAN",
|
||||
"role": "downstream",
|
||||
"services": [ "ssh" ],
|
||||
"ethernet": [
|
||||
{
|
||||
"select-ports": [
|
||||
"LAN*"
|
||||
]
|
||||
}
|
||||
],
|
||||
"ipv4": {
|
||||
"addressing": "static",
|
||||
"subnet": "192.168.1.1/24",
|
||||
"dhcp": {
|
||||
"lease-first": 10,
|
||||
"lease-count": 100,
|
||||
"lease-time": "6h"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
],
|
||||
"metrics": {
|
||||
"statistics": {
|
||||
"interval": 120,
|
||||
"types": [ "ssids", "lldp", "clients" ]
|
||||
},
|
||||
"health": {
|
||||
"interval": 120
|
||||
}
|
||||
},
|
||||
"services": {
|
||||
"ssh": {
|
||||
"port": 22
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
{
|
||||
"uuid": 2,
|
||||
"radios": [
|
||||
{
|
||||
"band": "5G",
|
||||
"country": "CA",
|
||||
"channel-mode": "HE",
|
||||
"channel-width": 80,
|
||||
"channel": 36
|
||||
}
|
||||
],
|
||||
|
||||
"interfaces": [
|
||||
{
|
||||
"name": "WAN",
|
||||
"role": "upstream",
|
||||
"ethernet": [
|
||||
{
|
||||
"select-ports": [
|
||||
"WAN*"
|
||||
]
|
||||
}
|
||||
],
|
||||
"ipv4": {
|
||||
"addressing": "dynamic"
|
||||
},
|
||||
"ssids": [
|
||||
{
|
||||
"name": "OpenWifi",
|
||||
"wifi-bands": [
|
||||
"2G", "5G"
|
||||
],
|
||||
"bss-mode": "ap",
|
||||
"encryption": {
|
||||
"proto": "wpa2",
|
||||
"ieee80211w": "optional"
|
||||
},
|
||||
"radius": {
|
||||
"authentication": {
|
||||
"host": "192.168.178.192",
|
||||
"port": 1812,
|
||||
"secret": "secret"
|
||||
},
|
||||
"accounting": {
|
||||
"host": "192.168.178.192",
|
||||
"port": 1813,
|
||||
"secret": "secret"
|
||||
}
|
||||
},
|
||||
"services": [ "radius-gw-proxy" ]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "LAN",
|
||||
"role": "downstream",
|
||||
"services": [ "ssh" ],
|
||||
"ethernet": [
|
||||
{
|
||||
"select-ports": [
|
||||
"LAN*"
|
||||
]
|
||||
}
|
||||
],
|
||||
"ipv4": {
|
||||
"addressing": "static",
|
||||
"subnet": "192.168.1.1/24",
|
||||
"dhcp": {
|
||||
"lease-first": 10,
|
||||
"lease-count": 100,
|
||||
"lease-time": "6h"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
],
|
||||
"metrics": {
|
||||
"statistics": {
|
||||
"interval": 120,
|
||||
"types": [ "ssids", "lldp", "clients" ]
|
||||
},
|
||||
"health": {
|
||||
"interval": 120
|
||||
}
|
||||
},
|
||||
"services": {
|
||||
"ssh": {
|
||||
"port": 22
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -103,14 +103,29 @@
|
||||
"radius-proxy": {
|
||||
"realms": [
|
||||
{
|
||||
"realm": "test",
|
||||
"protocol": "radsec",
|
||||
"realm": [ "radsec1", "radsec2" ],
|
||||
"host": "192.168.1.10",
|
||||
"secret": "secret",
|
||||
"ca-certificate": "Zm9vbwo=",
|
||||
"certificate": "Zm9vbwo=",
|
||||
"private-key": "Zm9vbwo="
|
||||
}, {
|
||||
"realm": "*",
|
||||
"protocol": "radius",
|
||||
"realm": [ "radius1", "radius2" ],
|
||||
"auth-server": "192.168.1.11",
|
||||
"auth-port": 1812,
|
||||
"auth-secret": "secret",
|
||||
"acct-server": "192.168.1.11",
|
||||
"acct-port": 1813,
|
||||
"acct-secret": "secret"
|
||||
}, {
|
||||
"protocol": "block",
|
||||
"realm": [ "block1", "block2" ],
|
||||
"message": "Access Denied"
|
||||
}, {
|
||||
"protocol": "radsec",
|
||||
"realm": [ "*" ],
|
||||
"auto-discover": true,
|
||||
"use-local-certificates": true
|
||||
}
|
||||
|
||||
@@ -1,23 +1,11 @@
|
||||
{
|
||||
"uuid": 2,
|
||||
"radios": [
|
||||
{
|
||||
"band": "6G",
|
||||
"country": "CA",
|
||||
"channel-mode": "HE",
|
||||
"channel-width": 80
|
||||
},
|
||||
{
|
||||
"band": "5G",
|
||||
"country": "CA",
|
||||
"channel-mode": "HE",
|
||||
"channel-width": 80
|
||||
},
|
||||
{
|
||||
"band": "2G",
|
||||
"country": "CA",
|
||||
"channel-mode": "HE",
|
||||
"channel-width": 80
|
||||
"channel": 1
|
||||
}
|
||||
],
|
||||
|
||||
@@ -49,13 +37,31 @@
|
||||
},
|
||||
"ipv4": {
|
||||
"addressing": "static",
|
||||
"subnet": "10.0.0.1/24"
|
||||
}
|
||||
"subnet": "10.0.0.2/24",
|
||||
"gateway": "10.0.0.1"
|
||||
},
|
||||
"ssids": [
|
||||
{
|
||||
"name": "OpenWifi-VXLAN",
|
||||
"wifi-bands": [
|
||||
"2G"
|
||||
],
|
||||
"bss-mode": "ap",
|
||||
"encryption": {
|
||||
"proto": "psk2",
|
||||
"key": "OpenWifi",
|
||||
"ieee80211w": "optional"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "LAN",
|
||||
"role": "downstream",
|
||||
"services": [ "ssh" ],
|
||||
"vlan": {
|
||||
"id": 100
|
||||
},
|
||||
"ethernet": [
|
||||
{
|
||||
"select-ports": [
|
||||
@@ -74,19 +80,15 @@
|
||||
},
|
||||
"ssids": [
|
||||
{
|
||||
"name": "Maverick",
|
||||
"name": "OpenWifi-VXLAN",
|
||||
"wifi-bands": [
|
||||
"5G",
|
||||
"2G"
|
||||
],
|
||||
"bss-mode": "ap",
|
||||
"encryption": {
|
||||
"proto": "none",
|
||||
"proto": "psk2",
|
||||
"key": "OpenWifi",
|
||||
"ieee80211w": "optional"
|
||||
},
|
||||
"roaming": {
|
||||
"message-exchange": "ds",
|
||||
"generate-psk": true
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
{
|
||||
"uuid": 2,
|
||||
"radios": [
|
||||
{
|
||||
"band": "2G",
|
||||
"country": "US",
|
||||
"channel-mode": "HE",
|
||||
"channel-width": 20,
|
||||
"channel": "auto"
|
||||
}, {
|
||||
"band": "5G",
|
||||
"country": "US",
|
||||
"channel-mode": "HE",
|
||||
"channel-width": 80,
|
||||
"channel": 36
|
||||
}, {
|
||||
"band": "6G",
|
||||
"country": "US",
|
||||
"channel-mode": "HE",
|
||||
"channel-width": 80,
|
||||
"channel": 33
|
||||
}
|
||||
],
|
||||
|
||||
"interfaces": [
|
||||
{
|
||||
"name": "WAN",
|
||||
"role": "upstream",
|
||||
"services": [ "lldp" ],
|
||||
"ethernet": [
|
||||
{
|
||||
"select-ports": [
|
||||
"WAN*"
|
||||
]
|
||||
}
|
||||
],
|
||||
"ipv4": {
|
||||
"addressing": "dynamic"
|
||||
},
|
||||
"ssids": [
|
||||
{
|
||||
"name": "OpenWifi2",
|
||||
"wifi-bands": [
|
||||
"2G"
|
||||
],
|
||||
"bss-mode": "ap",
|
||||
"encryption": {
|
||||
"proto": "psk2",
|
||||
"key": "OpenWifi",
|
||||
"ieee80211w": "optional"
|
||||
},
|
||||
"rrm": {
|
||||
"reduced-neighbor-reporting": true
|
||||
}
|
||||
}, {
|
||||
"name": "OpenWifi5",
|
||||
"wifi-bands": [
|
||||
"5G"
|
||||
],
|
||||
"bss-mode": "ap",
|
||||
"encryption": {
|
||||
"proto": "psk2",
|
||||
"key": "OpenWifi",
|
||||
"ieee80211w": "optional"
|
||||
},
|
||||
"rrm": {
|
||||
"reduced-neighbor-reporting": true
|
||||
}
|
||||
}, {
|
||||
"name": "OpenWifi6",
|
||||
"wifi-bands": [
|
||||
"6G"
|
||||
],
|
||||
"bss-mode": "ap",
|
||||
"encryption": {
|
||||
"proto": "sae",
|
||||
"key": "OpenWifi",
|
||||
"ieee80211w": "required"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "LAN",
|
||||
"role": "downstream",
|
||||
"services": [ "ssh", "lldp" ],
|
||||
"ethernet": [
|
||||
{
|
||||
"select-ports": [
|
||||
"LAN*"
|
||||
]
|
||||
}
|
||||
],
|
||||
"ipv4": {
|
||||
"addressing": "static",
|
||||
"subnet": "192.168.1.1/24",
|
||||
"dhcp": {
|
||||
"lease-first": 10,
|
||||
"lease-count": 100,
|
||||
"lease-time": "6h"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"metrics": {
|
||||
"statistics": {
|
||||
"interval": 120,
|
||||
"types": [ "ssids", "lldp", "clients" ]
|
||||
},
|
||||
"health": {
|
||||
"interval": 120
|
||||
}
|
||||
},
|
||||
"services": {
|
||||
"lldp": {
|
||||
"describe": "uCentral",
|
||||
"location": "universe"
|
||||
},
|
||||
"ssh": {
|
||||
"port": 22
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,12 +3,12 @@
|
||||
"radios": [
|
||||
{
|
||||
"band": "2G",
|
||||
"country": "CA",
|
||||
"country": "US",
|
||||
"channel-mode": "HE",
|
||||
"channel-width": 40
|
||||
}, {
|
||||
"band": "5G",
|
||||
"country": "CA",
|
||||
"country": "US",
|
||||
"channel-mode": "HE",
|
||||
"channel-width": 80
|
||||
}
|
||||
|
||||
13
feeds/ucentral/ucentral-schema/files/usr/bin/tcpdump_timeout
Executable file
13
feeds/ucentral/ucentral-schema/files/usr/bin/tcpdump_timeout
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
|
||||
n=$1
|
||||
shift
|
||||
|
||||
if [ $n -eq 0]; then
|
||||
tcpdump $@
|
||||
else
|
||||
tcpdump $@ &
|
||||
x=$!
|
||||
sleep $n
|
||||
kill $x
|
||||
fi
|
||||
16
feeds/ucentral/ucentral-schema/files/usr/share/ucentral/wifi_max_user.uc
Executable file
16
feeds/ucentral/ucentral-schema/files/usr/share/ucentral/wifi_max_user.uc
Executable file
@@ -0,0 +1,16 @@
|
||||
#!/usr/bin/ucode
|
||||
|
||||
let nl = require("nl80211");
|
||||
let def = nl.const;
|
||||
|
||||
function phy_get() {
|
||||
let res = nl.request(def.NL80211_CMD_GET_WIPHY, def.NLM_F_DUMP, { split_wiphy_dump: true });
|
||||
|
||||
if (res === false)
|
||||
warn("Unable to lookup phys: " + nl.error() + "\n");
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
let phys = phy_get();
|
||||
printf("%d\n", phys[0].max_ap_assoc);
|
||||
@@ -4,6 +4,7 @@ PKG_NAME:=ucentral-tools
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE_URL=https://github.com/blogic/ucentral-tools.git
|
||||
PKG_MIRROR_HASH:=9ae6a0cd431595871c233550427c4043c2ba7ddb3c5d87e46ab74a03b2b5a947
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_DATE:=2021-01-28
|
||||
PKG_SOURCE_VERSION:=b013fc636e48d407870a46aaa68a09ed74de8d6f
|
||||
|
||||
@@ -1,4 +1 @@
|
||||
[ ifup = "$ACTION" ] && {
|
||||
ip-collide
|
||||
[ $? -eq 0 ] || ubus call ucentral send '{"msg": "ip/domain collision detected", "severity": 3}'
|
||||
}
|
||||
[ ifup = "$ACTION" ] && /usr/share/ucentral/ip-collide.uc
|
||||
|
||||
@@ -4,9 +4,11 @@ PKG_NAME:=ucentral-wifi
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE_URL=https://github.com/blogic/ucentral-wifi.git
|
||||
PKG_MIRROR_HASH:=8e730a37026a37f113038ae27489bb92104d0a091403b7cc1f379188dddd2699
|
||||
#PKG_MIRROR_HASH:=b6a3bfbd0823c54bb6fb3899e583db8580474a24c1b238d97be152ea8eccf6e5
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_DATE:=2022-01-10
|
||||
PKG_SOURCE_VERSION:=955fed125e0597dda14cf52fb7224991072d6146
|
||||
PKG_SOURCE_VERSION:=aa9c3ee716929d75852a11640362a09bb32c5262
|
||||
|
||||
PKG_MAINTAINER:=John Crispin <john@phrozen.org>
|
||||
PKG_LICENSE:=BSD-3-Clause
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user