OpendayLight: How to specify the destination IP address of the flow table - json

I'm using OpendayLight(Carbon SR1) to send a flow table to the switch, everything is OK except working with the set-nw-dst-action-case instruction. Once I use this instruction, the flow can not be set to switch correctly(check via http://opendaylight_ip:8181/restconf/operational/opendaylight-inventory:nodes/node/openflow:1/flow-node-inventory:table/0)
and this is my json code to set the flow:
{
"flow": [
{
"id": "test",
"match": {
"ethernet-match": {
"ethernet-destination": {
"address": "02:42:4a:46:fc:02"
}
}
},
"instructions": {
"instruction": [
{
"order": "0",
"apply-actions": {
"action": [
{
"order": "0",
"set-nw-dst-action": {
"_Opps": "Remove this action goes normal"
"ipv4-address": "192.168.1.3/32"
}
},
{
"order": "1",
"set-dl-dst-action": {
"address": "02:42:4a:46:fc:03"
}
},
{
"order": "2",
"output-action": {
"output-node-connector": "3",
"max-length": "65535"
}
}
]
}
}
]
},
"priority": "16",
"table_id": "0"
}
]
}
The json code above follows the OpendayLight specification, but I found this message in Open vSwitch logs:
2017-09-07T16:35:26.713Z|00103|ofp_actions|WARN|set_field ip_dst lacks correct prerequisities
This question is similar to my one. I have tried to add flow with ovs-ofctl tools and succeed, is there any way to add the flow with set-nw-dst-action-case instruction in OpendayLight?
p.s. The ovs-ofctl command let:
ovs-ofctl add-flow s1 "table=0,dl_dst=02:42:4a:46:fc:02,priority=12,action=mod_dl_dst:02:42:4a:46:fc:03,mod_nw_dst:192.168.1.3,output:3"
EDIT(2017-9-8 21:14 GMT+8)
I have tried to match the ip criteria and the ovs log complain about this:
2017-09-08T12:49:30.567Z|00032|nx_match|WARN|Rejecting NXM/OXM entry 0:32768:12:1:8 with 1-bits in value for bits wildcarded by the mask.
2017-09-08T12:49:30.567Z|00033|ofp_actions|WARN|bad action at offset 0 (OFPBMC_BAD_WILDCARDS):
00000000 00 19 00 10 80 00 19 08-0a 00 00 03 ff 00 00 00
2017-09-08T12:49:30.567Z|00034|connmgr|INFO|s1<->tcp:192.168.43.171:6633: sending OFPBMC_BAD_WILDCARDS error reply to OFPT_FLOW_MOD message
2017-09-08T12:49:30.567Z|00035|ofp_actions|WARN|set_field ip_dst lacks correct prerequisities
and I use this json code(OpendayLight Yang UI passed):
{
"flow": [
{
"id": "bwt",
"match": {
"ethernet-match": {
"ethernet-destination": {
"address": "02:42:4a:46:fc:02"
}
},
"ipv4-destination": "192.168.1.2/32"
},
"instructions": {
"instruction": [
{
"order": "0",
"apply-actions": {
"action": [
{
"order": "0",
"set-dl-dst-action": {
"address": "02:42:4a:46:fc:03"
}
},
{
"order": "1",
"set-nw-src-action": {
"ipv4-address": "192.168.1.3/32"
}
},
{
"order": "2",
"output-action": {
"output-node-connector": "3",
"max-length": "65535"
}
}
]
}
}
]
},
"priority": "12",
"table_id": "0"
}
]
}
EDIT(2017-9-9 23:48 GMT+8)
The problem has been solved, see my answer.

Checkout openflow spec section 7.2.3.8, table:13(OXM_OF_IPV4_DST), as also error described in ovs log, you need to match packet type of ipv4 before setting action destination ip.
Sample Flow
ovs-ofctl add-flow s1 -O OpenFlow13 "table=0,ip,dl_dst=02:42:4a:46:fc:02,priority=12,action=set_field:02:42:4a:46:fc:03->eth_dst,set_field:192.168.1.3->ip_dst,output:3"

Specification
According to OpenFlow Switch Specification Version 1.3.5 ( Protocol version 0x04 ) section 7.2.3.6 Flow Match Field Prerequisite and section 7.2.3.8 Header Match Fields, the flow to modify the ip address(dst_ip or src_ip) have to:
1. set ethernet-destination-mask to ff:ff:ff:ff:ff:ff
2. ethernet-type-type to 0x0800.
3. The mask of ipv4 should be 255.255.255.255 or ip_addr/32
Code
The effective flow json code in OpendayLight platform as follows(Carbon SR1, opendaylight-inventory rev.2013-08-19):
{
"flow": [
{
"id": "bwt",
"match": {
"ethernet-match": {
"ethernet-destination": {
"address": "02:42:4a:46:fc:01",
"mask": "ff:ff:ff:ff:ff:ff"
},
"ethernet-type": {
"type": "0x0800"
}
},
"ipv4-destination": "192.168.1.2/32"
},
"instructions": {
"instruction": [
{
"order": "0",
"apply-actions": {
"action": [
{
"order": "0",
"set-dl-dst-action": {
"address": "02:42:4a:46:fc:03"
}
},
{
"order": "1",
"set-nw-dst-action": {
"ipv4-address": "192.168.1.3/32"
}
},
{
"order": "2",
"output-action": {
"output-node-connector": "3",
"max-length": "65535"
}
}
]
}
}
]
},
"priority": "12",
"table_id": "0"
}
]
}
Acknowledgment
Thanks to Karthik Prasad who guides me to read the specification and Peder Zickler who met the same problem as me.

Related

Geeting error in adding ssl certificate in cloudfront using cloudformation (needs to be specified)

{
"AWSTemplateFormatVersion" : "2010-09-09",
"Parameters": {
"AlternateDomainNames": {
"Description": "CNAMEs (alternate domain names), if any, for the distribution. Example. test.codavel.com",
"Type": "String",
"Default": "test.example.com"
}
},
"Resources" : {
"myDistribution" : {
"Type" : "AWS::CloudFront::Distribution",
"Properties" : {
"DistributionConfig" : {
"Origins" : [ {
"DomainName" : "ELBfor-1234.region.elb.amazonaws.com",
"Id" : "myCustomOrigin",
"CustomOriginConfig" : {
"HTTPPort" : "80",
"HTTPSPort" : "443",
"OriginProtocolPolicy" : "match-viewer",
"OriginSSLProtocols" : [
"TLSv1",
"TLSv1.1",
"TLSv1.2",
"SSLv3"
]
}
} ],
"HttpVersion": "http2",
"Aliases": [
{
"Ref": "AlternateDomainNames"
}
],
"Enabled" : "true",
"Comment" : "example-cdn",
"DefaultCacheBehavior" : {
"TargetOriginId" : "myCustomOrigin",
"SmoothStreaming" : "false",
"AllowedMethods": [
"HEAD",
"GET",
"OPTIONS"
],
"MaxTTL": "31536000",
"MinTTL": "0",
"Compress" : "true",
"ForwardedValues" : {
"QueryString" : "false",
"Cookies" : { "Forward" : "all" }
},
"ViewerProtocolPolicy" : "allow-all"
},
"PriceClass" : "PriceClass_All",
"Restrictions" : {
"GeoRestriction": {
"RestrictionType": "none",
"Locations": []
}
},
"ViewerCertificate": {
"SslSupportMethod": "sni-only",
"AcmCertificateArn" : {
"Fn::Sub": "arn:aws:acm:us-east-1:<ID>:certificate/2345f-534234"
}
}
}
}
}
}
}
Hi Team,
I am using this in my cloudfront template to add my custom SSL on that and it is showing me some an error:- Exactly one of [AcmCertificateArn,CloudFrontDefaultCertificate,IamCertificateId] needs to be specified.
So please let me know how will i add this or if there is any option to add in parameter so that it will list that certificate. Please guide me for the same. This is my certificate ARN - arn:aws:acm:us-east-1::certificate/2345f-534234
ViewerCertificate block should look like this in your case:
"ViewerCertificate": {
"SslSupportMethod": "sni-only",
"AcmCertificateArn": " arn:aws:acm:us-east-1::certificate/2345f-534234"
}
Also what you should always take care is that certificate is provisioned in us-east1 region (yours is, based on the ARN :)
The property you need to use is ViewerCertificate. The configuration within the CloudFormation documentation should help you identify any options you might want to add.
You can add a parameter if you would like to specify the ACM certificate, the type will be a string.
Below is an updated template. You will need to ensure th ACM certificate includes your account id. I have ran this to validate that it builds successfully.
{
"AWSTemplateFormatVersion": "2010-09-09",
"Parameters": {
"AlternateDomainNames": {
"Description": "CNAMEs (alternate domain names), if any, for the distribution. Example. test.codavel.com",
"Type": "String",
"Default": "test.example.com"
}
},
"Resources": {
"myDistribution": {
"Type": "AWS::CloudFront::Distribution",
"Properties": {
"DistributionConfig": {
"Origins": [{
"DomainName": "ELBfor-1234.region.elb.amazonaws.com",
"Id": "myCustomOrigin",
"CustomOriginConfig": {
"HTTPPort": "80",
"HTTPSPort": "443",
"OriginProtocolPolicy": "match-viewer",
"OriginSSLProtocols": [
"TLSv1",
"TLSv1.1",
"TLSv1.2",
"SSLv3"
]
}
}],
"ViewerCertificate": {
"SslSupportMethod": "sni-only",
"AcmCertificateArn": "arn:aws:acm:us-east-1::certificate/2345f-534234"
},
"HttpVersion": "http2",
"Aliases": [{
"Ref": "AlternateDomainNames"
}],
"Enabled": "true",
"Comment": "example-cdn",
"DefaultCacheBehavior": {
"TargetOriginId": "myCustomOrigin",
"SmoothStreaming": "false",
"AllowedMethods": [
"HEAD",
"GET",
"OPTIONS"
],
"MaxTTL": "31536000",
"MinTTL": "0",
"Compress": "true",
"ForwardedValues": {
"QueryString": "false",
"Cookies": {
"Forward": "all"
}
},
"ViewerProtocolPolicy": "allow-all"
},
"PriceClass": "PriceClass_All",
"Restrictions": {
"GeoRestriction": {
"RestrictionType": "none",
"Locations": []
}
}
}
}
}
}
}

GraphQL Query returns null objects both in GraphiQL and App from JSON data source

I'm trying to get my mocked JSON data via GraphQL in Gatsby. The response shows the correct data, but also two null objects as well. Why is it happening?
I'm using the gatsby-transformer.json plugin to query my data and gatsby-source-filesystem to point the transformer to my json files.
categories.json
the mock file I'm trying to get to work :)
{
"categories": [
{
"title": "DEZERTY",
"path": "/dezerty",
"categoryItems": [
{
"categoryName": "CUKRIKY",
"image": "../../../../static/img/dessertcategories/cukriky.jpg"
},
{
"categoryName": "NAHODNE",
"image": "../../../../static/img/dessertcategories/nahodne.jpg"
},
]
},
{
"title": "CANDY BAR",
"path": "/candy-bar",
"categoryItems": [
{
"categoryName": "CHEESECAKY",
"image": "../../../../static/img/dessertcategories/cheesecaky.jpg"
},
{
"categoryName": "BEZLEPKOVÉ TORTY",
"image": "../../../../static/img/dessertcategories/bezlepkove-torty.jpg"
},
]
}
]
}
GraphQL query in GraphiQL
query Collections {
allMockJson {
edges {
node {
categories {
categoryItems {
categoryName
image
}
title
path
}
}
}
}
}
And the response GraphiQL gives me
{
"data": {
"allMockJson": {
"edges": [
{
"node": {
"categories": null
}
},
{
"node": {
"categories": null
}
},
{
"node": {
"categories": [
{
"categoryItems": [
{
"categoryName": "CHEESECAKY",
"image": "../../../../static/img/dessertcategories/cheesecaky.jpg"
},
{
"categoryName": "BEZLEPKOVÉ TORTY",
"image": "../../../../static/img/dessertcategories/bezlepkove-torty.jpg"
}
],
"title": "DEZERTY",
"path": "/dezerty"
},
{
"categoryItems": [
{
"categoryName": "CUKRIKY",
"image": "../../../../static/img/dessertcategories/CUKRIKY.jpg"
},
{
"categoryName": "NAHODNE",
"image": "../../../../static/img/dessertcategories/NAHODNE.jpg"
}
],
"title": "CANDY BAR",
"path": "/candy-bar"
}
]
}
}
]
}
}
}
I expected only to get the DEZERTY and CANDY BAR sections. Why are there null categories and how do I fix it?
Thanks in advance
Your JSON contains syntax errors in the objects DEZERTY and CANDY BAR. It silently fails without telling you. Try this json linter.
Error: Parse error on line 12: },
Error: Parse error on line 25: },
Try again. Your query should work now.
You should look into an IDE that highlights these types of errors and saves you time and frustration.

JSON - Backslashes in Network Path

I have a PHP api which returns this JSON:
{
"recrutee": {
"recrutee_nom": "Mustermann",
"recrutee_statut": "Extern",
"recrutee_id_iam": "APP764",
"recrutee_debut_de_contrat": "2018-08-30",
"recrutee_fin_de_contrat": "2018-11-29",
"recrutee_prenom": "Max"
},
"responsable": {
"responsable_nom": "Musterman",
"responsable_prenom": "Marc",
"responsable_tel": "66666666",
"responsable_service": "It",
"responsable_email": "example#example.com"
},
"acces_reseau": [{
"path": "\\Some\Network\Path"
}],
"option_pc": [
{
"autre": "Nfc Reader"
}, {
"option": "internet"
}, {
"option": "lecteurluxtrust"
}, {
"option": "scanner"
}, {
"option": "imprimante"
}, {
"option": "ecransupplementaire"
}, {
"option": "lectuercodebarres"
}
],
"demande_id": "5b54588d00772",
"lieu": "Luxembourg City"
}
The problem is with the network path is it needs to look like this:
\\\\Some\\Network\\Path
Since backslashes are used as an escape character the network path in my original json is incorrect.
Is there any programatically (not manual) way to get this result:
\\\\Some\\Network\\Path

Query Nested Mongodb info with Variable Nested Field names

I have a MongoDB that is structured as below:
[
{
"subject_id": "1",
"name": "Maria",
"dob": "1/1/00",
"gender": "F",
"visits": {
"1/1/18": {
"date_entered": "1/2/18",
"entered_by": "Sally"
},
"1/2/18": {
"date_entered": "1/2/18",
"entered_by": "Tim",
}
},
"samples": {
"XXX123": {
"collected_by": "Sally",
"collection_date": "1/3/18"
}
}
},
{
"subject_id": "2",
"name": "Bob",
"dob": "1/2/00",
"gender": "M",
"visits": {
"1/3/18": {
"date_entered": "1/4/18",
"entered_by": "Tim"
}
},
"samples": {
"YYY456": {
"collected_by": "Sally",
"collection_date": "1/5/18"
},
"ZZZ789": {
"collected_by": "Tim",
"collection_date": "1/6/18"
},
"AAA123": {
"collected_by": "Sally",
"collection_date": "1/7/18"
}
}
}
]
If I wanted to query the database to find all samples collected by Sally or all visits entered by Tim, what would be the best way of doing that?
I'm new to MongoDB and my attempts with various regex's haven't produced results. Any advice would be greatly appreciated.
I first used project on the required fields to use objectToArray followed by unwind to create separate records for array created in project.
The results are then filtered using match.
This works for the data provided in the question -
db.so.aggregate([
{$project: {visits: {$objectToArray: "$visits"}, samples: {$objectToArray: "$samples"}}},
{$unwind: "$visits"},
{$unwind: "$samples"},
{ $match: {
$or : [
{ "visits.v.entered_by" : "Tim" },
{ "samples.v.collected_by" : "Sally" }
]
}
}
])

Set next step for the waterfall dialogue in Microsoft BotBuilder NodeJS SDK

I am using Microsoft Bot Framework for my facebook messenger bot. I want to load the dialog data from json files instead of hard coding in the js file. I would like to configure the next step in the dialog, based on result from the "current" step, which is part of the json file configuration, something like this.
{
"name": "welcome",
"type": "waterfall",
"steps": [
{
"id": 0,
"data": [
{
"type": "text",
"value": "Hey, It's nice to meet you."
},
{
"type": "quickReplies",
"value": "What do you want to do next?",
"options": [
{
"text": "some option 1",
"value": "option1"
},
{
"text": "some option 2",
"value": "option2"
}
]
}
],
"next": [
{
"result": "option1",
"action": "goto step 2"
},
{
"result": "option2",
"action": "goto step 5"
}
]
}
]
}
I would like to process all the incoming messages and respond with correct dialog or correct step in the dialog for the user.
I am trying something like this;
handleMessage = function (session) {
var step = session.dialogData["BotBuilder.Data.WaterfallStep"] || 0;
// check response data from previou step and identify the next step.
// set the waterfall step id
session.dialogData["BotBuilder.Data.WaterfallStep"] = 2;
session.send("Hello");
}
var bot = new builder.UniversalBot(connector, function (session) {
handleMessage(session);
})
.set('storage',tableStorage);
With this code, I am always getting step as zero for session.dialogData["BotBuilder.Data.WaterfallStep"] even after setting this to a different number.
Also, as soon as I set the waterfall step number, all other state data that is stored in my table storage for this conversation is gone.
Storage data before setting waterfall step:
{
"BotBuilder.Data.SessionState": {
"callstack": [
{
"id": "*:/",
"state": {
"BotBuilder.Data.WaterfallStep": 0
}
},
{
"id": "*:welcome",
"state": {
"BotBuilder.Data.WaterfallStep": 1
}
},
{
"id": "BotBuilder:prompt-text",
"state": {
"options": {
"prompt": {
"type": "message",
"agent": "botbuilder",
"source": "facebook",
"address": {
"id": "mid.$cAAAlr-0LRH9niO21L1hV6hs83GuJ",
"channelId": "facebook",
"user": {
"id": "XXXX",
"name": "XXXX"
},
"conversation": {
"isGroup": false,
"id": "XX"
},
"bot": {
"id": "XXX",
"name": "XXX"
},
"serviceUrl": "https://facebook.botframework.com"
},
"text": "what do you want to next"
//ignored for simplicity
},
"promptAfterAction": true,
"libraryNamespace": "*"
},
"turns": 0,
"lastTurn": 1517594116372,
"isReprompt": false
}
}
],
"lastAccess": 1517594112740,
"version": 0
}
}
After I set the waterfall step:
{
"BotBuilder.Data.SessionState": {
"callstack": [
{
"id": "*:/",
"state": {
"BotBuilder.Data.WaterfallStep": 2
}
}
],
"lastAccess": 1517602122416,
"version": 0
}
}
Interestingly the step number is saved to the database (but in session state) but my "session" variable do not have this value anywhere. Also, even after configuring custom state service, the serviceUrl is still https://facebook.botframework.com which I thought is the default state service used if there is no state service set for the bot.
Per your code, as your bot actually contains only one waterfall step: handleMessage(session);, which raised your issue. You can consider to create multiple dialogs from json configration instead of complex waterfall steps.
Here is my quick test, for your information:
const json = `
[{
"name": "welcome",
"type": "waterfall",
"steps": [
{
"id": 0,
"data": [
{
"type": "text",
"value": "Hey, It's nice to meet you."
},
{
"type": "quickReplies",
"value": "What do you want to do next?",
"options": [
{
"text": "some option 1",
"value": "option1"
},
{
"text": "some option 2",
"value": "option2"
}
]
}
],
"next": [
{
"result": "option1",
"action": "dialog2"
},
{
"result": "option2",
"action": "dialog3"
}
]
}
]
},{
"name":"dialog2",
"type": "waterfall",
"steps": [
{
"data": [
{
"type": "text",
"value": "Hey, this is dialig2."
}]
}
]
},{
"name":"dialog3",
"type": "waterfall",
"steps": [
{
"data": [
{
"type": "text",
"value": "Hey, this is dialig3."
}]
}
]
}]
`;
const generateSignleStep = (step) => {
return (session, args, next) => {
step.forEach(sentence => {
switch (sentence.type) {
case 'quickReplies':
let choices = sentence.options.map(item => {
return item.value
});
let card = new builder.ThumbnailCard(session)
.text(sentence.value)
.buttons(sentence.options.map(choice => new builder.CardAction.imBack(session, choice.value, choice.text)))
let message = new builder.Message(session).addAttachment(card);
builder.Prompts.choice(session, message, choices);
break;
case 'text':
default:
session.send(sentence.value)
break;
}
})
}
}
const generatenextAction = (actions) => {
return (session, args, next) => {
const response = args.response;
actions.map(action => {
if (action.result == response.entity) {
session.beginDialog(action.action);
}
})
}
}
const generateWaterfallSteps = (steps) => {
let waterfall = [];
steps.forEach(step => {
waterfall.push(generateSignleStep(step.data));
if (step.next) {
waterfall.push(generatenextAction(step.next));
}
});
return waterfall;
}
var bot = new builder.UniversalBot(connector);
const jsonobj = JSON.parse(json);
jsonobj.forEach(dialog => {
bot.dialog(dialog.name, generateWaterfallSteps(dialog.steps))
.triggerAction({
matches: new RegExp(dialog.name, "g")
})
});
The result is: